From 695aa482304f63377cc50df6f8fce856fdb10c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sun, 25 Jul 2010 09:25:57 +0200 Subject: [PATCH 01/79] Enable SDL_UpdateRects --- sdl/sdl.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sdl/sdl.go b/sdl/sdl.go index fd190cb..0d7a5b4 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -117,6 +117,12 @@ func (screen *Surface) UpdateRect(x int32, y int32, w uint32, h uint32) { C.SDL_UpdateRect((*C.SDL_Surface)(cast(screen)), C.Sint32(x), C.Sint32(y), C.Uint32(w), C.Uint32(h)) } +func (screen *Surface) UpdateRects(rects []Rect) { + if len(rects) > 0 { + C.SDL_UpdateRects((*C.SDL_Surface)(cast(screen)), C.int(len(rects)), (*C.SDL_Rect)(cast(&rects[0]))) + } +} + // Gets the window title and icon name. func WM_GetCaption() (title, icon string) { //SDL seems to free these strings. TODO: Check to see if that's the case From 74324fe5cc27204ce7ac79a505e97bb38b8f62af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 30 Jul 2010 21:30:56 +0200 Subject: [PATCH 02/79] Honestly, the Go-SDL package is a really naive wrapper. So, add locking in order to enable usage from multi-threaded applications. This fixes stuff in package "sdl" only, package "ttf" might not work from multiple threads. --- sdl/constants.6.go | 2 +- sdl/constants.8.go | 2 +- sdl/constants.c | 4 +- sdl/sdl.go | 356 +++++++++++++++++++++++++++++++++++++++------ ttf/ttf.go | 12 +- 5 files changed, 318 insertions(+), 58 deletions(-) diff --git a/sdl/constants.6.go b/sdl/constants.6.go index f3a98fa..eee3e97 100644 --- a/sdl/constants.6.go +++ b/sdl/constants.6.go @@ -349,7 +349,7 @@ const ( // Types -type Surface struct { +type InternalSurface struct { Flags uint32 Pad0 [4]byte Format *PixelFormat diff --git a/sdl/constants.8.go b/sdl/constants.8.go index a64c9d4..5839c26 100644 --- a/sdl/constants.8.go +++ b/sdl/constants.8.go @@ -349,7 +349,7 @@ const ( // Types -type Surface struct { +type InternalSurface struct { Flags uint32 Format *PixelFormat W int32 diff --git a/sdl/constants.c b/sdl/constants.c index f0f2c27..c0f8b77 100644 --- a/sdl/constants.c +++ b/sdl/constants.c @@ -3,12 +3,12 @@ // for i in `grep '#define SDL_.*0x' -r SDL_video.h | sed 's/\s/\n/g' | grep SDL_ | sed s/SDL_//` ; do echo -e "\t\$$i = SDL_$i," ; done -typedef SDL_Surface $Surface; +typedef SDL_Surface $InternalSurface; typedef SDL_PixelFormat $PixelFormat; typedef SDL_Rect $Rect; typedef SDL_Color $Color; typedef SDL_Palette $Palette; -typedef SDL_VideoInfo $VideoInfo; +typedef SDL_VideoInfo $internalVideoInfo; typedef SDL_Overlay $Overlay; typedef SDL_ActiveEvent $ActiveEvent; diff --git a/sdl/sdl.go b/sdl/sdl.go index 0d7a5b4..d9c9d11 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -17,60 +17,167 @@ package sdl // static void SetError(const char* description){SDL_SetError("%s",description);} import "C" import "unsafe" +import "sync" type cast unsafe.Pointer +var globalMutex sync.Mutex + +type Surface struct { + intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) + mutex sync.Mutex + + Flags uint32 + Format *PixelFormat + W int32 + H int32 + Pitch uint16 + Pixels *byte + Offset int32 +} + +// TODO: This should NOT be a public function, +// but since we need it in the package "ttf" ... the Go language sucks here +func Wrap(intSurface *InternalSurface) *Surface { + var s *Surface + + if intSurface != nil { + var surface Surface + surface.intSurface = intSurface + surface.reload() + s = &surface + } else { + s = nil + } + + return s +} + +// Pull data from the internal-surface. Make sure to use this when +// you expect that the internal-surface structure might have been changed. +func (s *Surface) reload() { + s.Flags = s.intSurface.Flags + s.Format = s.intSurface.Format + s.W = s.intSurface.W + s.H = s.intSurface.H + s.Pitch = s.intSurface.Pitch + s.Pixels = s.intSurface.Pixels + s.Offset = s.intSurface.Offset +} + +func (s *Surface) destroy() { + s.intSurface = nil + s.Format = nil + s.Pixels = nil +} + // General // Initializes SDL. -func Init(flags uint32) int { return int(C.SDL_Init(C.Uint32(flags))) } +func Init(flags uint32) int { + globalMutex.Lock() + status := int(C.SDL_Init(C.Uint32(flags))) + globalMutex.Unlock() + return status +} // Shuts down SDL -func Quit() { C.SDL_Quit() } +func Quit() { + globalMutex.Lock() + + if currentVideoSurface != nil { + currentVideoSurface.destroy() + currentVideoSurface = nil + } + + C.SDL_Quit() + + globalMutex.Unlock() +} // Initializes subsystems. -func InitSubSystem(flags uint32) int { return int(C.SDL_InitSubSystem(C.Uint32(flags))) } +func InitSubSystem(flags uint32) int { + globalMutex.Lock() + status := int(C.SDL_InitSubSystem(C.Uint32(flags))) + globalMutex.Unlock() + return status +} // Shuts down a subsystem. -func QuitSubSystem(flags uint32) { C.SDL_QuitSubSystem(C.Uint32(flags)) } +func QuitSubSystem(flags uint32) { + globalMutex.Lock() + C.SDL_QuitSubSystem(C.Uint32(flags)) + globalMutex.Unlock() +} // Checks which subsystems are initialized. -func WasInit(flags uint32) int { return int(C.SDL_WasInit(C.Uint32(flags))) } +func WasInit(flags uint32) int { + globalMutex.Lock() + status := int(C.SDL_WasInit(C.Uint32(flags))) + globalMutex.Unlock() + return status +} // Error Handling // Gets SDL error string -func GetError() string { return C.GoString(C.SDL_GetError()) } +func GetError() string { + globalMutex.Lock() + s := C.GoString(C.SDL_GetError()) + globalMutex.Unlock() + return s +} // Set a string describing an error to be submitted to the SDL Error system. func SetError(description string) { + globalMutex.Lock() + cdescription := C.CString(description) C.SetError(cdescription) C.free(unsafe.Pointer(cdescription)) + + globalMutex.Unlock() } // TODO SDL_Error // Clear the current SDL error -func ClearError() { C.SDL_ClearError() } +func ClearError() { + globalMutex.Lock() + C.SDL_ClearError() + globalMutex.Unlock() +} // Video +var currentVideoSurface *Surface = nil + // Sets up a video mode with the specified width, height, bits-per-pixel and // returns a corresponding surface. You don't need to call the Free method // of the returned surface, as it will be done automatically by sdl.Quit. func SetVideoMode(w int, h int, bpp int, flags uint32) *Surface { + globalMutex.Lock() var screen = C.SDL_SetVideoMode(C.int(w), C.int(h), C.int(bpp), C.Uint32(flags)) - return (*Surface)(cast(screen)) + currentVideoSurface = Wrap((*InternalSurface)(cast(screen))) + globalMutex.Unlock() + return currentVideoSurface } // Returns a pointer to the current display surface. -func GetVideoSurface() *Surface { return (*Surface)(cast(C.SDL_GetVideoSurface())) } +func GetVideoSurface() *Surface { + globalMutex.Lock() + surface := currentVideoSurface + globalMutex.Unlock() + return surface +} // Checks to see if a particular video mode is supported. Returns 0 if not // supported, or the bits-per-pixel of the closest available mode. func VideoModeOK(width int, height int, bpp int, flags uint32) int { - return int(C.SDL_VideoModeOK(C.int(width), C.int(height), C.int(bpp), C.Uint32(flags))) + globalMutex.Lock() + status := int(C.SDL_VideoModeOK(C.int(width), C.int(height), C.int(bpp), C.Uint32(flags))) + globalMutex.Unlock() + return status } type VideoInfo struct { @@ -90,7 +197,9 @@ type VideoInfo struct { } func GetVideoInfo() *VideoInfo { + globalMutex.Lock() vinfo := (*internalVideoInfo)(cast(C.SDL_GetVideoInfo())) + globalMutex.Unlock() flags := vinfo.Flags @@ -114,22 +223,39 @@ func GetVideoInfo() *VideoInfo { // Makes sure the given area is updated on the given screen. If x, y, w, and // h are all 0, the whole screen will be updated. func (screen *Surface) UpdateRect(x int32, y int32, w uint32, h uint32) { - C.SDL_UpdateRect((*C.SDL_Surface)(cast(screen)), C.Sint32(x), C.Sint32(y), C.Uint32(w), C.Uint32(h)) + globalMutex.Lock() + screen.mutex.Lock() + + C.SDL_UpdateRect((*C.SDL_Surface)(cast(screen.intSurface)), C.Sint32(x), C.Sint32(y), C.Uint32(w), C.Uint32(h)) + + screen.mutex.Unlock() + globalMutex.Unlock() } func (screen *Surface) UpdateRects(rects []Rect) { if len(rects) > 0 { - C.SDL_UpdateRects((*C.SDL_Surface)(cast(screen)), C.int(len(rects)), (*C.SDL_Rect)(cast(&rects[0]))) + globalMutex.Lock() + screen.mutex.Lock() + + C.SDL_UpdateRects((*C.SDL_Surface)(cast(screen.intSurface)), C.int(len(rects)), (*C.SDL_Rect)(cast(&rects[0]))) + + screen.mutex.Unlock() + globalMutex.Unlock() } } // Gets the window title and icon name. func WM_GetCaption() (title, icon string) { - //SDL seems to free these strings. TODO: Check to see if that's the case + globalMutex.Lock() + + // SDL seems to free these strings. TODO: Check to see if that's the case var ctitle, cicon *C.char C.SDL_WM_GetCaption(&ctitle, &cicon) title = C.GoString(ctitle) icon = C.GoString(cicon) + + globalMutex.Unlock() + return } @@ -137,79 +263,147 @@ func WM_GetCaption() (title, icon string) { func WM_SetCaption(title, icon string) { ctitle := C.CString(title) cicon := C.CString(icon) + + globalMutex.Lock() C.SDL_WM_SetCaption(ctitle, cicon) + globalMutex.Unlock() + C.free(unsafe.Pointer(ctitle)) C.free(unsafe.Pointer(cicon)) } // Sets the icon for the display window. func WM_SetIcon(icon *Surface, mask *uint8) { - C.SDL_WM_SetIcon((*C.SDL_Surface)(cast(icon)), (*C.Uint8)(mask)) + globalMutex.Lock() + C.SDL_WM_SetIcon((*C.SDL_Surface)(cast(icon.intSurface)), (*C.Uint8)(mask)) + globalMutex.Unlock() } // Minimizes the window -func WM_IconifyWindow() int { return int(C.SDL_WM_IconifyWindow()) } +func WM_IconifyWindow() int { + globalMutex.Lock() + status := int(C.SDL_WM_IconifyWindow()) + globalMutex.Unlock() + return status +} // Toggles fullscreen mode func WM_ToggleFullScreen(surface *Surface) int { - return int(C.SDL_WM_ToggleFullScreen((*C.SDL_Surface)(cast(surface)))) + globalMutex.Lock() + status := int(C.SDL_WM_ToggleFullScreen((*C.SDL_Surface)(cast(surface.intSurface)))) + globalMutex.Unlock() + return status } // Swaps OpenGL framebuffers/Update Display. -func GL_SwapBuffers() { C.SDL_GL_SwapBuffers() } +func GL_SwapBuffers() { + globalMutex.Lock() + C.SDL_GL_SwapBuffers() + globalMutex.Unlock() +} func GL_SetAttribute(attr int, value int) int { - return int(C.SDL_GL_SetAttribute(C.SDL_GLattr(attr), C.int(value))) + globalMutex.Lock() + status := int(C.SDL_GL_SetAttribute(C.SDL_GLattr(attr), C.int(value))) + globalMutex.Unlock() + return status } // Swaps screen buffers. -func (screen *Surface) Flip() int { return int(C.SDL_Flip((*C.SDL_Surface)(cast(screen)))) } +func (screen *Surface) Flip() int { + globalMutex.Lock() + screen.mutex.Lock() + + status := int(C.SDL_Flip((*C.SDL_Surface)(cast(screen.intSurface)))) + + screen.mutex.Unlock() + globalMutex.Unlock() + + return status +} // Frees (deletes) a Surface -func (screen *Surface) Free() { C.SDL_FreeSurface((*C.SDL_Surface)(cast(screen))) } +func (screen *Surface) Free() { + globalMutex.Lock() + screen.mutex.Lock() + + C.SDL_FreeSurface((*C.SDL_Surface)(cast(screen.intSurface))) + + screen.destroy() + if screen == currentVideoSurface { + currentVideoSurface = nil + } + + screen.mutex.Unlock() + globalMutex.Unlock() +} // Locks a surface for direct access. func (screen *Surface) Lock() int { - return int(C.SDL_LockSurface((*C.SDL_Surface)(cast(screen)))) + screen.mutex.Lock() + status := int(C.SDL_LockSurface((*C.SDL_Surface)(cast(screen.intSurface)))) + screen.mutex.Unlock() + return status } // Unlocks a previously locked surface. -func (screen *Surface) Unlock() int { return int(C.SDL_Flip((*C.SDL_Surface)(cast(screen)))) } +func (screen *Surface) Unlock() { + screen.mutex.Lock() + C.SDL_UnlockSurface((*C.SDL_Surface)(cast(screen.intSurface))) + screen.mutex.Unlock() +} func (dst *Surface) Blit(dstrect *Rect, src *Surface, srcrect *Rect) int { + src.mutex.Lock() + dst.mutex.Lock() + var ret = C.SDL_UpperBlit( - (*C.SDL_Surface)(cast(src)), + (*C.SDL_Surface)(cast(src.intSurface)), (*C.SDL_Rect)(cast(srcrect)), - (*C.SDL_Surface)(cast(dst)), + (*C.SDL_Surface)(cast(dst.intSurface)), (*C.SDL_Rect)(cast(dstrect))) + dst.mutex.Unlock() + src.mutex.Unlock() + return int(ret) } // This function performs a fast fill of the given rectangle with some color. func (dst *Surface) FillRect(dstrect *Rect, color uint32) int { + dst.mutex.Lock() + var ret = C.SDL_FillRect( - (*C.SDL_Surface)(cast(dst)), + (*C.SDL_Surface)(cast(dst.intSurface)), (*C.SDL_Rect)(cast(dstrect)), C.Uint32(color)) + dst.mutex.Unlock() + return int(ret) } // Adjusts the alpha properties of a Surface. func (s *Surface) SetAlpha(flags uint32, alpha uint8) int { - return int(C.SDL_SetAlpha((*C.SDL_Surface)(cast(s)), C.Uint32(flags), C.Uint8(alpha))) + s.mutex.Lock() + status := int(C.SDL_SetAlpha((*C.SDL_Surface)(cast(s.intSurface)), C.Uint32(flags), C.Uint8(alpha))) + s.mutex.Unlock() + return status } // Gets the clipping rectangle for a surface. func (s *Surface) GetClipRect(r *Rect) { - C.SDL_GetClipRect((*C.SDL_Surface)(cast(s)), (*C.SDL_Rect)(cast(r))) + s.mutex.Lock() + C.SDL_GetClipRect((*C.SDL_Surface)(cast(s.intSurface)), (*C.SDL_Rect)(cast(r))) + s.mutex.Unlock() return } // Sets the clipping rectangle for a surface. func (s *Surface) SetClipRect(r *Rect) { - C.SDL_SetClipRect((*C.SDL_Surface)(cast(s)), (*C.SDL_Rect)(cast(r))) + s.mutex.Lock() + C.SDL_SetClipRect((*C.SDL_Surface)(cast(s.intSurface)), (*C.SDL_Rect)(cast(r))) + s.mutex.Unlock() return } @@ -220,42 +414,63 @@ func GetRGBA(color uint32, format *PixelFormat, r, g, b, a *uint8) { // Loads Surface from file (using IMG_Load). func Load(file string) *Surface { + globalMutex.Lock() + cfile := C.CString(file) var screen = C.IMG_Load(cfile) C.free(unsafe.Pointer(cfile)) - return (*Surface)(cast(screen)) + + globalMutex.Unlock() + + return Wrap((*InternalSurface)(cast(screen))) } // Creates an empty Surface. func CreateRGBSurface(flags uint32, width int, height int, bpp int, Rmask uint32, Gmask uint32, Bmask uint32, Amask uint32) *Surface { + globalMutex.Lock() + p := C.SDL_CreateRGBSurface(C.Uint32(flags), C.int(width), C.int(height), C.int(bpp), C.Uint32(Rmask), C.Uint32(Gmask), C.Uint32(Bmask), C.Uint32(Amask)) - return (*Surface)(cast(p)) + + globalMutex.Unlock() + + return Wrap((*InternalSurface)(cast(p))) } // Events // Enables UNICODE translation. -func EnableUNICODE(enable int) int { return int(C.SDL_EnableUNICODE(C.int(enable))) } +func EnableUNICODE(enable int) int { + globalMutex.Lock() + previous := int(C.SDL_EnableUNICODE(C.int(enable))) + globalMutex.Unlock() + return previous +} // Sets keyboard repeat rate. func EnableKeyRepeat(delay, interval int) int { - return int(C.SDL_EnableKeyRepeat(C.int(delay), C.int(interval))) + globalMutex.Lock() + status := int(C.SDL_EnableKeyRepeat(C.int(delay), C.int(interval))) + globalMutex.Unlock() + return status } // Gets keyboard repeat rate. func GetKeyRepeat() (int, int) { - var delay int var interval int + globalMutex.Lock() C.SDL_GetKeyRepeat((*C.int)(cast(&delay)), (*C.int)(cast(&interval))) + globalMutex.Unlock() return delay, interval } // Gets a snapshot of the current keyboard state func GetKeyState() []uint8 { + globalMutex.Lock() + var numkeys C.int array := C.SDL_GetKeyState(&numkeys) @@ -263,6 +478,8 @@ func GetKeyState() []uint8 { *((**C.Uint8)(unsafe.Pointer(&ptr))) = array // TODO + globalMutex.Unlock() + return ptr } @@ -275,35 +492,68 @@ type Key C.int // Retrieves the current state of the mouse. func GetMouseState(x, y *int) uint8 { - return uint8(C.SDL_GetMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) + globalMutex.Lock() + state := uint8(C.SDL_GetMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) + globalMutex.Unlock() + return state } // Retrieves the current state of the mouse relative to the last time this // function was called. func GetRelativeMouseState(x, y *int) uint8 { - return uint8(C.SDL_GetRelativeMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) + globalMutex.Lock() + state := uint8(C.SDL_GetRelativeMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) + globalMutex.Unlock() + return state } // Gets the state of modifier keys -func GetModState() Mod { return Mod(C.SDL_GetModState()) } +func GetModState() Mod { + globalMutex.Lock() + state := Mod(C.SDL_GetModState()) + globalMutex.Unlock() + return state +} // Sets the state of modifier keys -func SetModState(modstate Mod) { C.SDL_SetModState(C.SDLMod(modstate)) } +func SetModState(modstate Mod) { + globalMutex.Lock() + C.SDL_SetModState(C.SDLMod(modstate)) + globalMutex.Unlock() +} // Gets the name of an SDL virtual keysym -func GetKeyName(key Key) string { return C.GoString(C.SDL_GetKeyName(C.SDLKey(key))) } +func GetKeyName(key Key) string { + globalMutex.Lock() + name := C.GoString(C.SDL_GetKeyName(C.SDLKey(key))) + globalMutex.Unlock() + return name +} // Events // Waits indefinitely for the next available event func (event *Event) Wait() bool { + globalMutex.Lock() var ret = C.SDL_WaitEvent((*C.SDL_Event)(cast(event))) + globalMutex.Unlock() return ret != 0 } // Polls for currently pending events func (event *Event) Poll() bool { + globalMutex.Lock() + var ret = C.SDL_PollEvent((*C.SDL_Event)(cast(event))) + + if ret != 0 { + if (event.Type == VIDEORESIZE) && (currentVideoSurface != nil) { + currentVideoSurface.reload() + } + } + + globalMutex.Unlock() + return ret != 0 } @@ -336,26 +586,36 @@ func (event *Event) MouseMotion() *MouseMotionEvent { // Returns ActiveEvent or nil if event has other type func (event *Event) Active() *ActiveEvent { - if event.Type == ACTIVEEVENT { - return (*ActiveEvent)(cast(event)) - } + if event.Type == ACTIVEEVENT { + return (*ActiveEvent)(cast(event)) + } - return nil + return nil } // Returns ResizeEvent or nil if event has other type func (event *Event) Resize() *ResizeEvent { - if event.Type == VIDEORESIZE { - return (*ResizeEvent)(cast(event)) - } + if event.Type == VIDEORESIZE { + return (*ResizeEvent)(cast(event)) + } - return nil + return nil } // Time // Gets the number of milliseconds since the SDL library initialization. -func GetTicks() uint32 { return uint32(C.SDL_GetTicks()) } +func GetTicks() uint32 { + globalMutex.Lock() + t := uint32(C.SDL_GetTicks()) + globalMutex.Unlock() + return t +} // Waits a specified number of milliseconds before returning. -func Delay(ms uint32) { C.SDL_Delay(C.Uint32(ms)) } +// TODO: This function is not needed in Go - eradicate it. +func Delay(ms uint32) { + globalMutex.Lock() + C.SDL_Delay(C.Uint32(ms)) + globalMutex.Unlock() +} diff --git a/ttf/ttf.go b/ttf/ttf.go index fd1232a..1201852 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -63,7 +63,7 @@ func RenderText_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderText_Solid(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return (*sdl.Surface)(unsafe.Pointer(surface)) + return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) } // Renders UTF-8 text in the specified color and returns an SDL surface. Solid @@ -73,7 +73,7 @@ func RenderUTF8_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderUTF8_Solid(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return (*sdl.Surface)(unsafe.Pointer(surface)) + return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) } // Renders Latin-1 text in the specified color (and with the specified background @@ -85,7 +85,7 @@ func RenderText_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S cbgcol := C.SDL_Color{C.Uint8(bgcolor.R), C.Uint8(bgcolor.G), C.Uint8(bgcolor.B), C.Uint8(bgcolor.Unused)} surface := C.TTF_RenderText_Shaded(font.cfont, ctext, ccol, cbgcol) C.free(unsafe.Pointer(ctext)) - return (*sdl.Surface)(unsafe.Pointer(surface)) + return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) } // Renders UTF-8 text in the specified color (and with the specified background @@ -97,7 +97,7 @@ func RenderUTF8_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S cbgcol := C.SDL_Color{C.Uint8(bgcolor.R), C.Uint8(bgcolor.G), C.Uint8(bgcolor.B), C.Uint8(bgcolor.Unused)} surface := C.TTF_RenderUTF8_Shaded(font.cfont, ctext, ccol, cbgcol) C.free(unsafe.Pointer(ctext)) - return (*sdl.Surface)(unsafe.Pointer(surface)) + return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) } // Renders Latin-1 text in the specified color and returns an SDL surface. @@ -108,7 +108,7 @@ func RenderText_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderText_Blended(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return (*sdl.Surface)(unsafe.Pointer(surface)) + return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) } // Renders UTF-8 text in the specified color and returns an SDL surface. @@ -119,7 +119,7 @@ func RenderUTF8_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderUTF8_Blended(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return (*sdl.Surface)(unsafe.Pointer(surface)) + return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) } // Returns the rendering style of the font. From 42617c49892eaaadc83f725145c260f3a6d10090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 19 Aug 2010 20:21:15 +0200 Subject: [PATCH 03/79] =?UTF-8?q?Add=20a=20funny=20"=E2=9A=9B"=20prefix=20?= =?UTF-8?q?(this=20enables=20to=20install=20this=20package=20in=20parallel?= =?UTF-8?q?=20with=20installing=20banthar/Go-SDL).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 4s/4s.go | 2 +- doc/template.go | 2 +- gfx/Makefile | 2 +- gfx/framerate.go | 2 +- mixer/Makefile | 6 +++++- sdl/Makefile | 6 +++++- test/Makefile | 2 +- test/test.go | 6 +++--- ttf/Makefile | 6 +++++- ttf/ttf.go | 2 +- 10 files changed, 24 insertions(+), 12 deletions(-) diff --git a/4s/4s.go b/4s/4s.go index 9c5415e..f44976b 100644 --- a/4s/4s.go +++ b/4s/4s.go @@ -8,7 +8,7 @@ package main import ( - "sdl" + "⚛sdl" "log" "os" "runtime" diff --git a/doc/template.go b/doc/template.go index 688f8f7..62c494b 100644 --- a/doc/template.go +++ b/doc/template.go @@ -1,7 +1,7 @@ package main import ( - "sdl" + "⚛sdl" ) func loadImage(name string) *sdl.Surface { diff --git a/gfx/Makefile b/gfx/Makefile index d98d37c..febaa0d 100644 --- a/gfx/Makefile +++ b/gfx/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.$(GOARCH) -TARG=sdl/gfx +TARG=⚛sdl/gfx GOFILES:=constants.go\ framerate.go diff --git a/gfx/framerate.go b/gfx/framerate.go index 60420a0..0ad3c4a 100644 --- a/gfx/framerate.go +++ b/gfx/framerate.go @@ -5,7 +5,7 @@ A pure Go version of SDL_framerate package gfx import ( - "sdl" + "⚛sdl" ) type FPSmanager struct { diff --git a/mixer/Makefile b/mixer/Makefile index fae1bb6..c30abbd 100644 --- a/mixer/Makefile +++ b/mixer/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.$(GOARCH) -TARG=sdl/mixer +TARG=⚛sdl/mixer GOFILES:=constants.go CGOFILES:=mixer.go @@ -13,3 +13,7 @@ CGO_LDFLAGS:=-lSDL_mixer CLEANFILES+=mixer include $(GOROOT)/src/Make.pkg + +_cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) + CGOPKGPATH=$(dir) $(QUOTED_GOBIN)/cgo -- $(CGO_CFLAGS) $(CGOFILES) + sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c diff --git a/sdl/Makefile b/sdl/Makefile index 29939cf..ed4b4e0 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.$(GOARCH) -TARG=sdl +TARG=⚛sdl GOFILES:=constants.$(O).go @@ -24,3 +24,7 @@ include $(GOROOT)/src/Make.pkg constants.$(O).go: constants.c godefs -g sdl constants.c > constants.$(O).go gofmt -w constants.$(O).go + +_cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) + CGOPKGPATH=$(dir) $(QUOTED_GOBIN)/cgo -- $(CGO_CFLAGS) $(CGOFILES) + sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c diff --git a/test/Makefile b/test/Makefile index 1ed8295..bfddc21 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.$(GOARCH) -TARG=test +TARG=⚛test GOFILES=test.go include $(GOROOT)/src/Make.cmd diff --git a/test/test.go b/test/test.go index 9ca85e9..e2270e5 100644 --- a/test/test.go +++ b/test/test.go @@ -1,9 +1,9 @@ package main import ( - "sdl" - "sdl/ttf" - "sdl/mixer" + "⚛sdl" + "⚛sdl/ttf" + "⚛sdl/mixer" "math" "fmt" ) diff --git a/ttf/Makefile b/ttf/Makefile index 2c92ff3..f1ade54 100644 --- a/ttf/Makefile +++ b/ttf/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.$(GOARCH) -TARG=sdl/ttf +TARG=⚛sdl/ttf GOFILES:=constants.go CGOFILES:=ttf.go @@ -13,3 +13,7 @@ CGO_LDFLAGS:=-lSDL_ttf CLEANFILES+=ttf include $(GOROOT)/src/Make.pkg + +_cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) + CGOPKGPATH=$(dir) $(QUOTED_GOBIN)/cgo -- $(CGO_CFLAGS) $(CGOFILES) + sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c diff --git a/ttf/ttf.go b/ttf/ttf.go index 1201852..3088754 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -9,7 +9,7 @@ package ttf // #include import "C" -import "sdl" +import "⚛sdl" import "unsafe" // A ttf or otf font. From 8a7d3730c37eabd4b887085bb97713e7b184a752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 25 Aug 2010 17:57:24 +0200 Subject: [PATCH 04/79] Update in response to Go release.2010-08-25 --- Makefile | 2 +- gfx/Makefile | 2 +- mixer/Makefile | 4 ++-- sdl/Makefile | 4 ++-- test/Makefile | 2 +- ttf/Makefile | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index d515007..28cff24 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc all: install diff --git a/gfx/Makefile b/gfx/Makefile index febaa0d..6a79896 100644 --- a/gfx/Makefile +++ b/gfx/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc TARG=⚛sdl/gfx diff --git a/mixer/Makefile b/mixer/Makefile index c30abbd..c3a3527 100644 --- a/mixer/Makefile +++ b/mixer/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc TARG=⚛sdl/mixer @@ -15,5 +15,5 @@ CLEANFILES+=mixer include $(GOROOT)/src/Make.pkg _cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) - CGOPKGPATH=$(dir) $(QUOTED_GOBIN)/cgo -- $(CGO_CFLAGS) $(CGOFILES) + CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c diff --git a/sdl/Makefile b/sdl/Makefile index ed4b4e0..f2d703d 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc TARG=⚛sdl @@ -26,5 +26,5 @@ constants.$(O).go: constants.c gofmt -w constants.$(O).go _cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) - CGOPKGPATH=$(dir) $(QUOTED_GOBIN)/cgo -- $(CGO_CFLAGS) $(CGOFILES) + CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c diff --git a/test/Makefile b/test/Makefile index bfddc21..4a5cdbc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc TARG=⚛test GOFILES=test.go diff --git a/ttf/Makefile b/ttf/Makefile index f1ade54..aded28c 100644 --- a/ttf/Makefile +++ b/ttf/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc TARG=⚛sdl/ttf @@ -15,5 +15,5 @@ CLEANFILES+=ttf include $(GOROOT)/src/Make.pkg _cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) - CGOPKGPATH=$(dir) $(QUOTED_GOBIN)/cgo -- $(CGO_CFLAGS) $(CGOFILES) + CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c From 9f4339553ea83a85868214ad72454f896b85edf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 26 Aug 2010 18:59:41 +0200 Subject: [PATCH 05/79] Minor Makefile updates. See also http://groups.google.com/group/golang-nuts/browse_thread/thread/2e1521c155a19f83 --- mixer/Makefile | 4 ---- sdl/Makefile | 2 +- test/Makefile | 2 +- ttf/Makefile | 4 ---- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/mixer/Makefile b/mixer/Makefile index c3a3527..1dd7828 100644 --- a/mixer/Makefile +++ b/mixer/Makefile @@ -13,7 +13,3 @@ CGO_LDFLAGS:=-lSDL_mixer CLEANFILES+=mixer include $(GOROOT)/src/Make.pkg - -_cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) - CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) - sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c diff --git a/sdl/Makefile b/sdl/Makefile index f2d703d..1935123 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -25,6 +25,6 @@ constants.$(O).go: constants.c godefs -g sdl constants.c > constants.$(O).go gofmt -w constants.$(O).go -_cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) +_cgo_defun.c: $(CGOFILES) CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c diff --git a/test/Makefile b/test/Makefile index 4a5cdbc..4670fb3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.inc -TARG=⚛test +TARG=test GOFILES=test.go include $(GOROOT)/src/Make.cmd diff --git a/ttf/Makefile b/ttf/Makefile index aded28c..35c474a 100644 --- a/ttf/Makefile +++ b/ttf/Makefile @@ -13,7 +13,3 @@ CGO_LDFLAGS:=-lSDL_ttf CLEANFILES+=ttf include $(GOROOT)/src/Make.pkg - -_cgo_defun.c _cgo_gotypes.go _cgo_export.c _cgo_export.h: $(CGOFILES) - CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) - sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c From 30be0280a17f29b452d06419d84c769e6142b06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Tue, 31 Aug 2010 13:48:51 +0200 Subject: [PATCH 06/79] Remove sdl.GetTicks and sdl.Delay --- doc/template.go | 3 ++- gfx/framerate.go | 68 ++++++++++++++++++++++++------------------------ sdl/sdl.go | 17 ------------ test/test.go | 3 ++- 4 files changed, 38 insertions(+), 53 deletions(-) diff --git a/doc/template.go b/doc/template.go index 62c494b..68688ed 100644 --- a/doc/template.go +++ b/doc/template.go @@ -2,6 +2,7 @@ package main import ( "⚛sdl" + "time" ) func loadImage(name string) *sdl.Surface { @@ -48,7 +49,7 @@ func main() { //screen.Blit(&sdl.Rect{x,y, 0, 0}, image, nil) screen.Flip() - sdl.Delay(25) + time.Sleep(25*1e6) } diff --git a/gfx/framerate.go b/gfx/framerate.go index 0ad3c4a..1de8896 100644 --- a/gfx/framerate.go +++ b/gfx/framerate.go @@ -5,53 +5,53 @@ A pure Go version of SDL_framerate package gfx import ( - "⚛sdl" + "time" ) type FPSmanager struct { - framecount uint32 - rateticks float - lastticks uint32 - rate uint32 + framecount uint32 + rateticks float + lastticks uint64 + rate uint32 } func NewFramerate() *FPSmanager { - return &FPSmanager{ - framecount: 0, - rate: FPS_DEFAULT, - rateticks: (1000.0 / float(FPS_DEFAULT)), - lastticks: sdl.GetTicks(), - } + return &FPSmanager{ + framecount: 0, + rate: FPS_DEFAULT, + rateticks: (1000.0 / float(FPS_DEFAULT)), + lastticks: uint64(time.Nanoseconds()) / 1e6, + } } func (manager *FPSmanager) SetFramerate(rate uint32) { - if rate >= FPS_LOWER_LIMIT && rate <= FPS_UPPER_LIMIT { - manager.framecount = 0 - manager.rate = rate - manager.rateticks = 1000.0 / float(rate) - } else { - } + if rate >= FPS_LOWER_LIMIT && rate <= FPS_UPPER_LIMIT { + manager.framecount = 0 + manager.rate = rate + manager.rateticks = 1000.0 / float(rate) + } else { + } } func (manager *FPSmanager) GetFramerate() uint32 { - return manager.rate + return manager.rate } func (manager *FPSmanager) FramerateDelay() { - var current_ticks, target_ticks, the_delay uint32 - - // next frame - manager.framecount++ - - // get/calc ticks - current_ticks = sdl.GetTicks() - target_ticks = manager.lastticks + uint32(float(manager.framecount) * manager.rateticks) - - if current_ticks <= target_ticks { - the_delay = target_ticks - current_ticks - sdl.Delay(the_delay) - } else { - manager.framecount = 0 - manager.lastticks = sdl.GetTicks() - } + var current_ticks, target_ticks, the_delay uint64 + + // next frame + manager.framecount++ + + // get/calc ticks + current_ticks = uint64(time.Nanoseconds()) / 1e6 + target_ticks = manager.lastticks + uint64(float(manager.framecount)*manager.rateticks) + + if current_ticks <= target_ticks { + the_delay = target_ticks - current_ticks + time.Sleep(int64(the_delay) * 1e6) + } else { + manager.framecount = 0 + manager.lastticks = uint64(time.Nanoseconds()) / 1e6 + } } diff --git a/sdl/sdl.go b/sdl/sdl.go index d9c9d11..1015334 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -602,20 +602,3 @@ func (event *Event) Resize() *ResizeEvent { return nil } -// Time - -// Gets the number of milliseconds since the SDL library initialization. -func GetTicks() uint32 { - globalMutex.Lock() - t := uint32(C.SDL_GetTicks()) - globalMutex.Unlock() - return t -} - -// Waits a specified number of milliseconds before returning. -// TODO: This function is not needed in Go - eradicate it. -func Delay(ms uint32) { - globalMutex.Lock() - C.SDL_Delay(C.Uint32(ms)) - globalMutex.Unlock() -} diff --git a/test/test.go b/test/test.go index e2270e5..2e49211 100644 --- a/test/test.go +++ b/test/test.go @@ -6,6 +6,7 @@ import ( "⚛sdl/mixer" "math" "fmt" + "time" ) type Point struct { @@ -177,7 +178,7 @@ func main() { worm_in <- p screen.Flip() - sdl.Delay(25) + time.Sleep(25*1e6) } image.Free() From 6f250b4186df4557ef327d6e30d990ecddcf2e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 2 Sep 2010 17:19:18 +0200 Subject: [PATCH 07/79] Use a Go channel for delivering events. --- Makefile | 1 + TODO | 22 ------------- doc/Makefile | 6 ++++ doc/template.go | 39 +++++++++++----------- sdl/Makefile | 8 ++--- sdl/event.go | 52 +++++++++++++++++++++++++++++ sdl/sdl.go | 83 ++++++++++------------------------------------ test/test.go | 88 ++++++++++++++++++++++++------------------------- 8 files changed, 142 insertions(+), 157 deletions(-) create mode 100644 doc/Makefile create mode 100644 sdl/event.go diff --git a/Makefile b/Makefile index 28cff24..3097e5b 100644 --- a/Makefile +++ b/Makefile @@ -19,3 +19,4 @@ clean: make -C 4s clean make -C test clean make -C gfx clean + make -C doc clean diff --git a/TODO b/TODO index 42f1a03..1c1b9ce 100644 --- a/TODO +++ b/TODO @@ -1,25 +1,3 @@ -* permanently fix KeyboardEvent issue - - Go, unlike C, adds pading before nested structures. - - struct A {uint8 n=0x11} - struct B {uint8 n=0x22, A a} - - in c this will result in raw data: - 22 11 - in Go - 22 00 00 00 11 - - This results in misaligned Keysym field. - - This is currently fixed by adding or removing some fields. - Accessor function in C would probably be better solution. - - // static SDL_keysym* KeyboardEvent_GetKeySym(SDL_KeyboardEvent *e){return &(e->keysym);} - import "C" - - func (event *KeyboardEvent) Keysym() *Keysym { return (*Keysym)(cast(C.KeyboardEvent_GetKeySym((*C.SDL_KeyboardEvent)(cast(event))))); } - * missing functions, threads and file access are useless in Go, but there are probably some usefull functions left * add joystick support * other SDL libraries: SGE, gfx ... diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..7d84aaf --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,6 @@ +include $(GOROOT)/src/Make.inc + +TARG=template +GOFILES=template.go + +include $(GOROOT)/src/Make.cmd diff --git a/doc/template.go b/doc/template.go index 68688ed..6f8c962 100644 --- a/doc/template.go +++ b/doc/template.go @@ -2,6 +2,8 @@ package main import ( "⚛sdl" + "fmt" + "rand" "time" ) @@ -17,40 +19,37 @@ func loadImage(name string) *sdl.Surface { } func main() { - - if sdl.Init(sdl.INIT_EVERYTHING) != 0 { + if sdl.Init(sdl.INIT_VIDEO) != 0 { panic(sdl.GetError()) } defer sdl.Quit() - var screen = sdl.SetVideoMode(640, 480, 32, 0) - + screen := sdl.SetVideoMode(400, 300, 32, 0) if screen == nil { panic(sdl.GetError()) } sdl.WM_SetCaption("Template", "") - for true { + ticker := time.NewTicker(1e9 / 2 /*2 Hz*/ ) - e := &sdl.Event{} +loop: + for { + select { + case <-ticker.C: + // Note: For better efficiency, use UpdateRects instead of Flip + screen.FillRect(nil, /*color*/ rand.Uint32()) + //screen.Blit(&sdl.Rect{x,y, 0, 0}, image, nil) + screen.Flip() - for e.Poll() { - switch e.Type { - case sdl.QUIT: - return - default: + case event := <-sdl.Events: + fmt.Printf("%#v\n", event) + + switch e := event.(type) { + case sdl.QuitEvent: + break loop } } - - screen.FillRect(nil, 0x000000) - - //screen.Blit(&sdl.Rect{x,y, 0, 0}, image, nil) - - screen.Flip() - time.Sleep(25*1e6) - } - } diff --git a/sdl/Makefile b/sdl/Makefile index 1935123..07fbabe 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -6,19 +6,17 @@ include $(GOROOT)/src/Make.inc TARG=⚛sdl -GOFILES:=constants.$(O).go +GOFILES:=\ + constants.$(O).go\ + event.go # uncomment this line to enable exp/draw support # GOFILES:=$(GOFILES) sdldraw.go CGOFILES:=sdl.go - CGO_LDFLAGS:=`pkg-config --libs sdl` -lSDL_image - CGO_CFLAGS:=`pkg-config --cflags sdl` -CLEANFILES+=sdl - include $(GOROOT)/src/Make.pkg constants.$(O).go: constants.c diff --git a/sdl/event.go b/sdl/event.go new file mode 100644 index 0000000..5e73a79 --- /dev/null +++ b/sdl/event.go @@ -0,0 +1,52 @@ +package sdl + +import "time" + +var events chan interface{} = make(chan interface{}) + +// This channel delivers SDL events. Each object received from this channel +// has one of the following types: sdl.QuitEvent, sdl.KeyboardEvent, +// sdl.MouseButtonEvent, sdl.MouseMotionEvent, sdl.ActiveEvent, +// sdl.ResizeEvent. +var Events <-chan interface{} = events + +// Polling interval, in milliseconds +const poll_interval_ms = 10 + +// Polls SDL events in periodic intervals. +// This function does not return. +func pollEvents() { + // It is more efficient to create the event-object here once, + // rather than multiple times within the loop + event := &Event{} + + for { + for event.poll() { + switch event.Type { + case QUIT: + events <- *(*QuitEvent)(cast(event)) + + case KEYDOWN, KEYUP: + events <- *(*KeyboardEvent)(cast(event)) + + case MOUSEBUTTONDOWN, MOUSEBUTTONUP: + events <- *(*MouseButtonEvent)(cast(event)) + + case MOUSEMOTION: + events <- *(*MouseMotionEvent)(cast(event)) + + case ACTIVEEVENT: + events <- *(*ActiveEvent)(cast(event)) + + case VIDEORESIZE: + events <- *(*ResizeEvent)(cast(event)) + } + } + + time.Sleep(poll_interval_ms * 1e6) + } +} + +func init() { + go pollEvents() +} diff --git a/sdl/sdl.go b/sdl/sdl.go index 1015334..d26a037 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -25,7 +25,7 @@ var globalMutex sync.Mutex type Surface struct { intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) - mutex sync.Mutex + mutex sync.RWMutex Flags uint32 Format *PixelFormat @@ -56,13 +56,17 @@ func Wrap(intSurface *InternalSurface) *Surface { // Pull data from the internal-surface. Make sure to use this when // you expect that the internal-surface structure might have been changed. func (s *Surface) reload() { - s.Flags = s.intSurface.Flags - s.Format = s.intSurface.Format - s.W = s.intSurface.W - s.H = s.intSurface.H - s.Pitch = s.intSurface.Pitch - s.Pixels = s.intSurface.Pixels - s.Offset = s.intSurface.Offset + s.mutex.Lock() + { + s.Flags = s.intSurface.Flags + s.Format = s.intSurface.Format + s.W = s.intSurface.W + s.H = s.intSurface.H + s.Pitch = s.intSurface.Pitch + s.Pixels = s.intSurface.Pixels + s.Offset = s.intSurface.Offset + } + s.mutex.Unlock() } func (s *Surface) destroy() { @@ -354,7 +358,7 @@ func (screen *Surface) Unlock() { } func (dst *Surface) Blit(dstrect *Rect, src *Surface, srcrect *Rect) int { - src.mutex.Lock() + src.mutex.RLock() dst.mutex.Lock() var ret = C.SDL_UpperBlit( @@ -364,7 +368,7 @@ func (dst *Surface) Blit(dstrect *Rect, src *Surface, srcrect *Rect) int { (*C.SDL_Rect)(cast(dstrect))) dst.mutex.Unlock() - src.mutex.Unlock() + src.mutex.RUnlock() return int(ret) } @@ -393,9 +397,9 @@ func (s *Surface) SetAlpha(flags uint32, alpha uint8) int { // Gets the clipping rectangle for a surface. func (s *Surface) GetClipRect(r *Rect) { - s.mutex.Lock() + s.mutex.RLock() C.SDL_GetClipRect((*C.SDL_Surface)(cast(s.intSurface)), (*C.SDL_Rect)(cast(r))) - s.mutex.Unlock() + s.mutex.RUnlock() return } @@ -532,16 +536,8 @@ func GetKeyName(key Key) string { // Events -// Waits indefinitely for the next available event -func (event *Event) Wait() bool { - globalMutex.Lock() - var ret = C.SDL_WaitEvent((*C.SDL_Event)(cast(event))) - globalMutex.Unlock() - return ret != 0 -} - // Polls for currently pending events -func (event *Event) Poll() bool { +func (event *Event) poll() bool { globalMutex.Lock() var ret = C.SDL_PollEvent((*C.SDL_Event)(cast(event))) @@ -557,48 +553,3 @@ func (event *Event) Poll() bool { return ret != 0 } -// Returns KeyboardEvent or nil if event has other type -func (event *Event) Keyboard() *KeyboardEvent { - if event.Type == KEYUP || event.Type == KEYDOWN { - return (*KeyboardEvent)(cast(event)) - } - - return nil -} - -// Returns MouseButtonEvent or nil if event has other type -func (event *Event) MouseButton() *MouseButtonEvent { - if event.Type == MOUSEBUTTONDOWN || event.Type == MOUSEBUTTONUP { - return (*MouseButtonEvent)(cast(event)) - } - - return nil -} - -// Returns MouseMotion or nil if event has other type -func (event *Event) MouseMotion() *MouseMotionEvent { - if event.Type == MOUSEMOTION { - return (*MouseMotionEvent)(cast(event)) - } - - return nil -} - -// Returns ActiveEvent or nil if event has other type -func (event *Event) Active() *ActiveEvent { - if event.Type == ACTIVEEVENT { - return (*ActiveEvent)(cast(event)) - } - - return nil -} - -// Returns ResizeEvent or nil if event has other type -func (event *Event) Resize() *ResizeEvent { - if event.Type == VIDEORESIZE { - return (*ResizeEvent)(cast(event)) - } - - return nil -} - diff --git a/test/test.go b/test/test.go index 2e49211..919eab6 100644 --- a/test/test.go +++ b/test/test.go @@ -29,7 +29,6 @@ func worm(in <-chan Point, out chan<- Point, draw chan<- Point) { t := Point{0, 0} for { - p := (<-in).sub(t) if p.length() > 48 { @@ -115,18 +114,43 @@ func main() { out = make(chan Point) go worm(in, out, draw) + ticker := time.NewTicker(1e9/50 /*50Hz*/) + + // Note: The following SDL code is highly ineffective. + // It is eating too much CPU. If you intend to use Go-SDL, + // you should to do better than this. + for running { + select { + case <-ticker.C: + screen.FillRect(nil, 0x302019) + screen.Blit(&sdl.Rect{0, 0, 0, 0}, text, nil) + + loop: for { + select { + case p := <-draw: + screen.Blit(&sdl.Rect{int16(p.x), int16(p.y), 0, 0}, image, nil) + + case <-out: + default: + break loop + } + } - e := &sdl.Event{} + var p Point + sdl.GetMouseState(&p.x, &p.y) + worm_in <- p - for e.Poll() { - switch e.Type { - case sdl.QUIT: + screen.Flip() + + case _event := <-sdl.Events: + switch e := _event.(type) { + case sdl.QuitEvent: running = false - break - case sdl.KEYDOWN, sdl.KEYUP: + + case sdl.KeyboardEvent: println("") - println(e.Keyboard().Keysym.Sym, ": ", sdl.GetKeyName(sdl.Key(e.Keyboard().Keysym.Sym))) + println(e.Keysym.Sym, ": ", sdl.GetKeyName(sdl.Key(e.Keysym.Sym))) fmt.Printf("%04x ", e.Type) @@ -135,50 +159,26 @@ func main() { } println() - k := e.Keyboard() + fmt.Printf("Type: %02x Which: %02x State: %02x Pad: %02x\n", e.Type, e.Which, e.State, e.Pad0[0]) + fmt.Printf("Scancode: %02x Sym: %08x Mod: %04x Unicode: %04x\n", e.Keysym.Scancode, e.Keysym.Sym, e.Keysym.Mod, e.Keysym.Unicode) + case sdl.MouseButtonEvent: + if e.Type == sdl.MOUSEBUTTONDOWN { + println("Click:", e.X, e.Y) + in = out + out = make(chan Point) + go worm(in, out, draw) + } - fmt.Printf("Type: %02x Which: %02x State: %02x Pad: %02x\n", k.Type, k.Which, k.State, k.Pad0[0]) - fmt.Printf("Scancode: %02x Sym: %08x Mod: %04x Unicode: %04x\n", k.Keysym.Scancode, k.Keysym.Sym, k.Keysym.Mod, k.Keysym.Unicode) - case sdl.MOUSEBUTTONDOWN: - println("Click:", e.MouseButton().X, e.MouseButton().Y) - in = out - out = make(chan Point) - go worm(in, out, draw) - case sdl.VIDEORESIZE: - println("resize screen ",e.Resize().W, e.Resize().H); + case sdl.ResizeEvent: + println("resize screen ", e.W, e.H) - screen = sdl.SetVideoMode(int(e.Resize().W), int(e.Resize().H), 32, sdl.RESIZABLE) + screen = sdl.SetVideoMode(int(e.W), int(e.H), 32, sdl.RESIZABLE) if screen == nil { panic(sdl.GetError()) } - default: } } - - screen.FillRect(nil, 0x302019) - screen.Blit(&sdl.Rect{0, 0, 0, 0}, text, nil) - - loop := true - - for loop { - - select { - case p := <-draw: - screen.Blit(&sdl.Rect{int16(p.x), int16(p.y), 0, 0}, image, nil) - case <-out: - default: - loop = false - } - - } - - var p Point - sdl.GetMouseState(&p.x, &p.y) - worm_in <- p - - screen.Flip() - time.Sleep(25*1e6) } image.Free() From c1cac45db440a24c150fe1acaebb6255eee0d9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 6 Sep 2010 16:38:50 +0200 Subject: [PATCH 08/79] Add support for SDL low-level sound API --- .gitignore | 21 ++--- Makefile | 2 + README | 5 -- README.md | 24 +++++ sdl/audio/Makefile | 24 +++++ sdl/audio/audio.go | 206 +++++++++++++++++++++++++++++++++++++++++++ sdl/audio/callback.c | 138 +++++++++++++++++++++++++++++ sdl/audio/callback.h | 15 ++++ sdl/sdl.go | 1 - 9 files changed, 417 insertions(+), 19 deletions(-) delete mode 100644 README create mode 100644 README.md create mode 100644 sdl/audio/Makefile create mode 100644 sdl/audio/audio.go create mode 100644 sdl/audio/callback.c create mode 100644 sdl/audio/callback.h diff --git a/.gitignore b/.gitignore index e1d0eaf..358d7c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,10 @@ -**~ -main -**.o -**.8 -**.6 -.obj/ -**.cgo*.go -**.cgo*.c -**.cgo*.8 -**.cgo*.6 -**/_obj -**/*.out +*~ +*.[o68] +_obj +*.cgo*.go +*.cgo*.c +*.cgo*.[68] +*.out test/test shoot.png -**_cgo* \ No newline at end of file +*_cgo* diff --git a/Makefile b/Makefile index 3097e5b..c89e062 100644 --- a/Makefile +++ b/Makefile @@ -8,12 +8,14 @@ all: install install: make -C sdl install + make -C sdl/audio install make -C ttf install make -C mixer install make -C gfx install clean: make -C sdl clean + make -C sdl/audio clean make -C ttf clean make -C mixer clean make -C 4s clean diff --git a/README b/README deleted file mode 100644 index d77bb90..0000000 --- a/README +++ /dev/null @@ -1,5 +0,0 @@ -Make sure you have SDL, SDL_image, SDL_mixer, and SDL_ttf (all in -dev version). - -If the bindings fail to compile, run 'hg pull -u' in $GOROOT and rebuild Go. The release version of Go doesn't have some changes necessary to build the ttf and mixer bindings last I checked. - -Music to test SDL_mixer is by Kevin MacLeod. diff --git a/README.md b/README.md new file mode 100644 index 0000000..050097d --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Introduction + +This is an improved version of Banthar's [Go-SDL](http://github.com/banthar/Go-SDL). + +The improvements/differences are: + +* SDL functions (maybe except for SDL-ttf) can be safely called from multiple concurrent goroutines +* All SDL events are delivered via a Go channel +* Support for low-level SDL sound functions + +* Can be installed in parallel to Banthar's Go-SDL +* The import path is "⚛sdl", instead of "sdl" + + +# Installation + +Make sure you have SDL, SDL-image, SDL-mixer, and SDL-ttf (all in -dev version). + +To install, run 'make' in the top-level directory. If it fails to compile, try to run 'hg pull; hg update release' in $GOROOT and rebuild Go. + + +# Credits + +Music to test SDL-mixer is by Kevin MacLeod. diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile new file mode 100644 index 0000000..ea0a39e --- /dev/null +++ b/sdl/audio/Makefile @@ -0,0 +1,24 @@ +include $(GOROOT)/src/Make.inc + +TARG=⚛sdl/audio + +CGOFILES=audio.go +CGO_LDFLAGS=callback.o `pkg-config --libs sdl` +CGO_CFLAGS=`pkg-config --cflags sdl` + +include $(GOROOT)/src/Make.pkg + +_cgo_defun.c: $(CGOFILES) + CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) + sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c + +_cgo_defun.c: callback.h + + +_obj/$(TARG).a: callback.o +_cgo_.so: callback.o + +callback.o: callback.c + $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.c + +callback.o: callback.h diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go new file mode 100644 index 0000000..403360d --- /dev/null +++ b/sdl/audio/audio.go @@ -0,0 +1,206 @@ +/* + * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 + * + * The contents of this file can be used freely, + * except for usages in immoral contexts. + */ + +package audio + +// #include +// #include "callback.h" +import "C" +import "unsafe" +import "sync" + +// Audio format +const ( + AUDIO_U8 = C.AUDIO_U8 + AUDIO_S8 = C.AUDIO_S8 + AUDIO_U16LSB = C.AUDIO_U16LSB + AUDIO_S16LSB = C.AUDIO_S16LSB + AUDIO_U16MSB = C.AUDIO_U16MSB + AUDIO_S16MSB = C.AUDIO_S16MSB + AUDIO_U16 = C.AUDIO_U16 + AUDIO_S16 = C.AUDIO_S16 +) + +// Native audio byte ordering +const ( + AUDIO_U16SYS = C.AUDIO_U16SYS + AUDIO_S16SYS = C.AUDIO_S16SYS +) + +type AudioSpec struct { + Freq int + Format uint16 // If in doubt, use AUDIO_S16SYS + Channels uint8 // 1 or 2 + Out_Silence uint8 + Samples uint16 // A power of 2, preferrably 2^11 (2048) or more + Out_Size uint32 +} + +func OpenAudio(desired, obtained_orNil *AudioSpec) int { + mutex.Lock() + opened++ + mutex.Unlock() + + var C_desired, C_obtained *C.SDL_AudioSpec + + C_desired = new(C.SDL_AudioSpec) + C_desired.freq = C.int(desired.Freq) + C_desired.format = C.Uint16(desired.Format) + C_desired.channels = C.Uint8(desired.Channels) + C_desired.samples = C.Uint16(desired.Samples) + C_desired.callback = C.callback_getCallback() + + if obtained_orNil != nil { + if desired != obtained_orNil { + C_obtained = new(C.SDL_AudioSpec) + } else { + C_obtained = C_desired + } + } + + status := C.SDL_OpenAudio(C_desired, C_obtained) + + if obtained_orNil != nil { + obtained := obtained_orNil + + obtained.Freq = int(C_obtained.freq) + obtained.Format = uint16(C_obtained.format) + obtained.Channels = uint8(C_obtained.channels) + obtained.Samples = uint16(C_obtained.samples) + obtained.Out_Silence = uint8(C_obtained.silence) + obtained.Out_Size = uint32(C_obtained.size) + } + + return int(status) +} + +func CloseAudio() { + mutex.Lock() + { + opened-- + switch { + case opened == 0: + userPaused = true + sdlPaused = true + case opened < 0: + panic("SDL audio not opened") + } + } + mutex.Unlock() + + C.callback_unblock() + + C.SDL_CloseAudio() +} + +// Audio status +const ( + SDL_AUDIO_STOPPED = C.SDL_AUDIO_STOPPED + SDL_AUDIO_PLAYING = C.SDL_AUDIO_PLAYING + SDL_AUDIO_PAUSED = C.SDL_AUDIO_PAUSED +) + +func GetAudioStatus() int { + return int(C.SDL_GetAudioStatus()) +} + +var opened int = 0 + +var userPaused bool = true +var sdlPaused bool = true +var haveData bool = false + +var mutex sync.Mutex + +// Pause or unpause the audio. +// Unpausing is deferred until a SendAudio function receives some samples. +func PauseAudio(pause_on bool) { + mutex.Lock() + + if pause_on != sdlPaused { + if pause_on { + // Pause SDL audio + userPaused = true + sdlPaused = true + C.SDL_PauseAudio(1) + } else { + userPaused = false + if haveData { + // Unpause SDL audio + sdlPaused = false + C.SDL_PauseAudio(0) + } else { + // Defer until SendAudio is called + } + } + } + + mutex.Unlock() +} + +func LockAudio() { + C.SDL_LockAudio() +} + +func UnlockAudio() { + C.SDL_UnlockAudio() +} + + +// Send samples to the audio device (AUDIO_S16SYS format). +// This function blocks until all the samples are consumed by the SDL audio thread. +func SendAudio_int16(data []int16) { + if len(data) > 0 { + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + } +} + +// Send samples to the audio device (AUDIO_U16SYS format). +// This function blocks until all the samples are consumed by the SDL audio thread. +func SendAudio_uint16(data []uint16) { + if len(data) > 0 { + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + } +} + +// Send samples to the audio device (AUDIO_S8 format). +// This function blocks until all the samples are consumed by the SDL audio thread. +func SendAudio_int8(data []int8) { + if len(data) > 0 { + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + } +} + +// Send samples to the audio device (AUDIO_U8 format). +// This function blocks until all the samples are consumed by the SDL audio thread. +func SendAudio_uint8(data []uint8) { + if len(data) > 0 { + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + } +} + +func sendAudio(data *C.Uint8, numBytes C.size_t) { + if numBytes > 0 { + mutex.Lock() + { + haveData = true + + if (userPaused == false) && (sdlPaused == true) { + // Unpause SDL audio + sdlPaused = false + C.SDL_PauseAudio(0) + } + } + mutex.Unlock() + + C.callback_fillBuffer(data, numBytes) + + mutex.Lock() + haveData = false + mutex.Unlock() + } +} diff --git a/sdl/audio/callback.c b/sdl/audio/callback.c new file mode 100644 index 0000000..1faa1b5 --- /dev/null +++ b/sdl/audio/callback.c @@ -0,0 +1,138 @@ +/* + * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 + * + * The contents of this file can be used freely, + * except for usages in immoral contexts. + */ + +#include "callback.h" +#include +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t need = PTHREAD_COND_INITIALIZER; +static pthread_cond_t avail = PTHREAD_COND_INITIALIZER; +static size_t needed = 0; // Number of bytes needed by the consumer +static size_t available = 0; // Number of bytes available (from the producer) + +static Uint8 *stream; // Communication buffer between the consumer and the producer + +static int64_t get_time() { + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + return 1000000000*(int64_t)ts.tv_sec + (int64_t)ts.tv_nsec; + else + return -1; +} + +static uint64_t cummulativeLatency = 0; +static unsigned numCallbacks = 0; + +static void SDLCALL callback(void *userdata, Uint8 *_stream, int _len) { + assert(_len > 0); + + size_t len = (size_t)_len; + + pthread_mutex_lock(&m); + { + assert(available == 0); + stream = _stream; + + { + int64_t t1 = get_time(); + //printf("consumer: t1=%lld µs\n", (long long)t1/1000); + + assert(needed == 0); + //printf("consumer: needed <- %zu\n", len); + needed = len; + pthread_cond_signal(&need); + + //printf("consumer: waiting for data\n"); + pthread_cond_wait(&avail, &m); + assert(needed == 0); + assert(available == len); + + int64_t t2 = get_time(); + //printf("consumer: t2=%lld µs\n", (long long)t2/1000); + if(t1>0 && t2>0) { + uint64_t latency = t2-t1; + cummulativeLatency += latency; + numCallbacks++; + /*printf("consumer: latency=%lld µs, avg=%u µs\n", + (long long)(latency/1000), + (unsigned)(cummulativeLatency/numCallbacks/1000));*/ + } + } + + //printf("consumer: received %zu bytes of data\n", available); + + //printf("consumer: available <- 0\n"); + available = 0; + stream = NULL; + } + pthread_mutex_unlock(&m); +} + +callback_t callback_getCallback() { + return &callback; +} + +void callback_fillBuffer(Uint8 *data, size_t numBytes) { + size_t sent = 0; + + pthread_mutex_lock(&m); + + while(sent < numBytes) { + //int64_t t = get_time(); + //printf("producer: t=%lld µs\n", (long long)t1/1000); + + if(needed == 0) { + //printf("producer: waiting until data is needed (1)\n"); + pthread_cond_wait(&need, &m); + } + + assert(stream != NULL); + assert(needed > 0); + + // Append a chunk of data to the 'stream' + size_t n = (needed<(numBytes-sent)) ? needed : (numBytes-sent); + memcpy(stream+available, data+sent, n); + available += n; + sent += n; + needed -= n; + + //printf("producer: added %zu bytes, available=%zu\n", n, available); + + if(needed == 0) { + pthread_cond_signal(&avail); + if(sent < numBytes) { + //printf("producer: waiting until data is needed (2)\n"); + pthread_cond_wait(&need, &m); + } + else { + break; + } + } + } + + pthread_mutex_unlock(&m); +} + +void callback_unblock() { + pthread_mutex_lock(&m); + if(needed > 0) { + // Note: SDL already prefilled the entire 'stream' with silence + assert(stream != NULL); + available += needed; + needed = 0; + pthread_cond_signal(&avail); + } + pthread_mutex_unlock(&m); +} + diff --git a/sdl/audio/callback.h b/sdl/audio/callback.h new file mode 100644 index 0000000..fdde71b --- /dev/null +++ b/sdl/audio/callback.h @@ -0,0 +1,15 @@ +/* + * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 + * + * The contents of this file can be used freely, + * except for usages in immoral contexts. + */ + +#include + +typedef void (SDLCALL *callback_t)(void *userdata, Uint8 *stream, int len); + +extern callback_t callback_getCallback(); +extern void callback_fillBuffer(Uint8 *data, size_t numBytes); +extern void callback_unblock(); + diff --git a/sdl/sdl.go b/sdl/sdl.go index d26a037..5fd432f 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -552,4 +552,3 @@ func (event *Event) poll() bool { return ret != 0 } - From 07d3f060942c5afe81b2a752aab91e267e0ac729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Tue, 7 Sep 2010 17:52:15 +0200 Subject: [PATCH 09/79] Allow CloseAudio() to interrupt an ongoing audio-data send --- sdl/audio/callback.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sdl/audio/callback.c b/sdl/audio/callback.c index 1faa1b5..c6cde14 100644 --- a/sdl/audio/callback.c +++ b/sdl/audio/callback.c @@ -95,6 +95,12 @@ void callback_fillBuffer(Uint8 *data, size_t numBytes) { if(needed == 0) { //printf("producer: waiting until data is needed (1)\n"); pthread_cond_wait(&need, &m); + + // Interrupted from 'callback_unblock' ? + if(needed == 0) { + //printf("producer: interrupted (1)\n"); + break; + } } assert(stream != NULL); @@ -114,6 +120,12 @@ void callback_fillBuffer(Uint8 *data, size_t numBytes) { if(sent < numBytes) { //printf("producer: waiting until data is needed (2)\n"); pthread_cond_wait(&need, &m); + + // Interrupted from 'callback_unblock' ? + if(needed == 0) { + //printf("producer: interrupted (2)\n"); + break; + } } else { break; @@ -133,6 +145,7 @@ void callback_unblock() { needed = 0; pthread_cond_signal(&avail); } + pthread_cond_signal(&need); pthread_mutex_unlock(&m); } From a3a579d0c5e7aa24dd4a884fe892c3cb31ab3dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 10 Sep 2010 12:02:22 +0200 Subject: [PATCH 10/79] Ignore *cgo*.so files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 358d7c2..e683b37 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ _obj *.cgo*.go *.cgo*.c *.cgo*.[68] +*cgo*.so *.out test/test shoot.png From 47ac34343eaea9e0671a338d3b22b44eba7f8d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 10 Sep 2010 19:15:01 +0200 Subject: [PATCH 11/79] Add Go-SDL version descriptors --- sdl/audio/audio.go | 12 ++++++++++++ sdl/sdl.go | 28 ++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 403360d..29acccc 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -13,6 +13,18 @@ import "C" import "unsafe" import "sync" +// The version of Go-SDL audio bindings. +// The version descriptor changes into a new unique string +// after a semantically incompatible Go-SDL update. +// +// The returned value can be checked by users of this package +// to make sure they are using a version with the expected semantics. +// +// If Go adds some kind of support for package versioning, this function will go away. +func GoSdlAudioVersion() string { + return "⚛SDL audio bindings 1.0" +} + // Audio format const ( AUDIO_U8 = C.AUDIO_U8 diff --git a/sdl/sdl.go b/sdl/sdl.go index 5fd432f..1478e00 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -75,7 +75,22 @@ func (s *Surface) destroy() { s.Pixels = nil } + +// ======= // General +// ======= + +// The version of Go-SDL bindings. +// The version descriptor changes into a new unique string +// after a semantically incompatible Go-SDL update. +// +// The returned value can be checked by users of this package +// to make sure they are using a version with the expected semantics. +// +// If Go adds some kind of support for package versioning, this function will go away. +func GoSdlVersion() string { + return "⚛SDL bindings 1.0" +} // Initializes SDL. func Init(flags uint32) int { @@ -122,7 +137,10 @@ func WasInit(flags uint32) int { return status } + +// ============== // Error Handling +// ============== // Gets SDL error string func GetError() string { @@ -143,8 +161,6 @@ func SetError(description string) { globalMutex.Unlock() } -// TODO SDL_Error - // Clear the current SDL error func ClearError() { globalMutex.Lock() @@ -152,7 +168,10 @@ func ClearError() { globalMutex.Unlock() } + +// ====== // Video +// ====== var currentVideoSurface *Surface = nil @@ -441,7 +460,10 @@ func CreateRGBSurface(flags uint32, width int, height int, bpp int, Rmask uint32 return Wrap((*InternalSurface)(cast(p))) } + +// ====== // Events +// ====== // Enables UNICODE translation. func EnableUNICODE(enable int) int { @@ -534,8 +556,6 @@ func GetKeyName(key Key) string { return name } -// Events - // Polls for currently pending events func (event *Event) poll() bool { globalMutex.Lock() From 2097424cfdc09c68f0c52113a50911c2a0250bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 13 Sep 2010 20:34:26 +0200 Subject: [PATCH 12/79] Add SDL_ShowCursor --- sdl/constants.6.go | 3 ++ sdl/constants.8.go | 3 ++ sdl/constants.c | 6 ++++ sdl/sdl.go | 80 +++++++++++++++++++++++++++------------------- 4 files changed, 59 insertions(+), 33 deletions(-) diff --git a/sdl/constants.6.go b/sdl/constants.6.go index eee3e97..2874e29 100644 --- a/sdl/constants.6.go +++ b/sdl/constants.6.go @@ -82,6 +82,9 @@ const ( VIDEOEXPOSEMASK = 0x20000 QUITMASK = 0x1000 SYSWMEVENTMASK = 0x2000 + QUERY = -1 + DISABLE = 0 + ENABLE = 1 K_UNKNOWN = 0 K_FIRST = 0 K_BACKSPACE = 0x8 diff --git a/sdl/constants.8.go b/sdl/constants.8.go index 5839c26..9643aef 100644 --- a/sdl/constants.8.go +++ b/sdl/constants.8.go @@ -82,6 +82,9 @@ const ( VIDEOEXPOSEMASK = 0x20000 QUITMASK = 0x1000 SYSWMEVENTMASK = 0x2000 + QUERY = -1 + DISABLE = 0 + ENABLE = 1 K_UNKNOWN = 0 K_FIRST = 0 K_BACKSPACE = 0x8 diff --git a/sdl/constants.c b/sdl/constants.c index c0f8b77..97f11dc 100644 --- a/sdl/constants.c +++ b/sdl/constants.c @@ -121,6 +121,12 @@ enum $QUITMASK = SDL_QUITMASK, $SYSWMEVENTMASK = SDL_SYSWMEVENTMASK, +// event state + + $QUERY = SDL_QUERY, + $DISABLE = SDL_DISABLE, + $ENABLE = SDL_ENABLE, + // keys $K_UNKNOWN = SDLK_UNKNOWN, $K_FIRST = SDLK_FIRST, diff --git a/sdl/sdl.go b/sdl/sdl.go index 1478e00..15ea40f 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -37,7 +37,7 @@ type Surface struct { } // TODO: This should NOT be a public function, -// but since we need it in the package "ttf" ... the Go language sucks here +// but since we need it in the package "ttf" ... the Go language is failing here func Wrap(intSurface *InternalSurface) *Surface { var s *Surface @@ -54,19 +54,15 @@ func Wrap(intSurface *InternalSurface) *Surface { } // Pull data from the internal-surface. Make sure to use this when -// you expect that the internal-surface structure might have been changed. +// the internal-surface might have been changed. func (s *Surface) reload() { - s.mutex.Lock() - { - s.Flags = s.intSurface.Flags - s.Format = s.intSurface.Format - s.W = s.intSurface.W - s.H = s.intSurface.H - s.Pitch = s.intSurface.Pitch - s.Pixels = s.intSurface.Pixels - s.Offset = s.intSurface.Offset - } - s.mutex.Unlock() + s.Flags = s.intSurface.Flags + s.Format = s.intSurface.Format + s.W = s.intSurface.W + s.H = s.intSurface.H + s.Pitch = s.intSurface.Pitch + s.Pixels = s.intSurface.Pixels + s.Offset = s.intSurface.Offset } func (s *Surface) destroy() { @@ -461,9 +457,9 @@ func CreateRGBSurface(flags uint32, width int, height int, bpp int, Rmask uint32 } -// ====== -// Events -// ====== +// ======== +// Keyboard +// ======== // Enables UNICODE translation. func EnableUNICODE(enable int) int { @@ -516,23 +512,6 @@ type Mod C.int // Key type Key C.int -// Retrieves the current state of the mouse. -func GetMouseState(x, y *int) uint8 { - globalMutex.Lock() - state := uint8(C.SDL_GetMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) - globalMutex.Unlock() - return state -} - -// Retrieves the current state of the mouse relative to the last time this -// function was called. -func GetRelativeMouseState(x, y *int) uint8 { - globalMutex.Lock() - state := uint8(C.SDL_GetRelativeMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) - globalMutex.Unlock() - return state -} - // Gets the state of modifier keys func GetModState() Mod { globalMutex.Lock() @@ -556,6 +535,11 @@ func GetKeyName(key Key) string { return name } + +// ====== +// Events +// ====== + // Polls for currently pending events func (event *Event) poll() bool { globalMutex.Lock() @@ -572,3 +556,33 @@ func (event *Event) poll() bool { return ret != 0 } + + +// ===== +// Mouse +// ===== + +// Retrieves the current state of the mouse. +func GetMouseState(x, y *int) uint8 { + globalMutex.Lock() + state := uint8(C.SDL_GetMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) + globalMutex.Unlock() + return state +} + +// Retrieves the current state of the mouse relative to the last time this +// function was called. +func GetRelativeMouseState(x, y *int) uint8 { + globalMutex.Lock() + state := uint8(C.SDL_GetRelativeMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) + globalMutex.Unlock() + return state +} + +// Toggle whether or not the cursor is shown on the screen. +func ShowCursor(toggle int) int { + globalMutex.Lock() + state := int(C.SDL_ShowCursor((C.int)(toggle))) + globalMutex.Unlock() + return state +} From 61e5f0d242942d3fe742acafe8708c0da331e999 Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Tue, 14 Sep 2010 16:53:07 +0200 Subject: [PATCH 13/79] Run gofmt --- sdl/structs.6.go | 5 ++--- sdl/structs.8.go | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/sdl/structs.6.go b/sdl/structs.6.go index 42a7086..3b4ed93 100644 --- a/sdl/structs.6.go +++ b/sdl/structs.6.go @@ -3,9 +3,8 @@ package sdl import "sync" type Surface struct { - intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) - mutex sync.RWMutex - + intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) + mutex sync.RWMutex Flags uint32 Pad0 [4]byte Format *PixelFormat diff --git a/sdl/structs.8.go b/sdl/structs.8.go index 82f5cd9..b9b9bf7 100644 --- a/sdl/structs.8.go +++ b/sdl/structs.8.go @@ -3,9 +3,8 @@ package sdl import "sync" type Surface struct { - intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) - mutex sync.RWMutex - + intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) + mutex sync.RWMutex Flags uint32 Format *PixelFormat W int32 From 76fc3193316defffef4022fcd91fcd6b6e777583 Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Tue, 14 Sep 2010 22:36:53 +0200 Subject: [PATCH 14/79] Fix makefiles --- sdl/Makefile | 5 +++++ test/Makefile | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sdl/Makefile b/sdl/Makefile index 48d6fb1..3326dc0 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -17,3 +17,8 @@ include $(GOROOT)/src/Make.pkg constants.go: constants.c godefs -g sdl constants.c > constants.go gofmt -w constants.go + +_cgo_defun.c: $(CGOFILES) + CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) + sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c + diff --git a/test/Makefile b/test/Makefile index 4670fb3..4a5cdbc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.inc -TARG=test +TARG=⚛test GOFILES=test.go include $(GOROOT)/src/Make.cmd From d851d41a96aaa958201ff2be4cdca8b81b9889b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 15 Sep 2010 13:25:09 +0200 Subject: [PATCH 15/79] Apply fixes to the last merge, remove "sdldraw.go" --- .gitignore | 14 ----- sdl/Makefile | 5 -- sdl/constants.c | 2 - sdl/constants.go | 18 ------ sdl/sdl.go | 150 ++++++++++++++++++++++++++--------------------- sdl/sdldraw.go | 140 ------------------------------------------- sdl/structs.6.go | 24 -------- sdl/structs.8.go | 22 ------- test/Makefile | 2 +- test/test.go | 12 +--- ttf/ttf.go | 26 ++++++-- 11 files changed, 107 insertions(+), 308 deletions(-) delete mode 100644 sdl/sdldraw.go diff --git a/.gitignore b/.gitignore index 5374069..e683b37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -<<<<<<< HEAD *~ *.[o68] _obj @@ -10,16 +9,3 @@ _obj test/test shoot.png *_cgo* -======= -**~ -main -**.[o86] -.obj/ -**.cgo*.* -**/_obj -**/*.out -test/test -shoot.png -**_cgo* -*.so ->>>>>>> dd437a47253d3fac5aef44016bc2a4d5d35f3e34 diff --git a/sdl/Makefile b/sdl/Makefile index 3326dc0..bad3334 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -5,13 +5,9 @@ TARG=⚛sdl GOFILES:=constants.go event.go structs.$(O).go CGOFILES:=sdl.go - CGO_LDFLAGS:=`pkg-config --libs sdl` -lSDL_image - CGO_CFLAGS:=`pkg-config --cflags sdl` -CLEANFILES+=sdl - include $(GOROOT)/src/Make.pkg constants.go: constants.c @@ -21,4 +17,3 @@ constants.go: constants.c _cgo_defun.c: $(CGOFILES) CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c - diff --git a/sdl/constants.c b/sdl/constants.c index 91750ca..b8f4af5 100644 --- a/sdl/constants.c +++ b/sdl/constants.c @@ -1,7 +1,5 @@ #include -typedef SDL_Surface $InternalSurface; - enum { diff --git a/sdl/constants.go b/sdl/constants.go index 3ed0590..0fae0ec 100644 --- a/sdl/constants.go +++ b/sdl/constants.go @@ -334,21 +334,3 @@ const ( ) // Types - -type InternalSurface struct { - Flags uint32 - Format *[40]byte /* SDL_PixelFormat */ - W int32 - H int32 - Pitch uint16 - Pad0 [2]byte - Pixels *byte - Offset int32 - Hwdata *[0]byte /* sprivate_hwdata */ - Clip_rect [8]byte /* SDL_Rect */ - Unused1 uint32 - Locked uint32 - Map *[0]byte /* sSDL_BlitMap */ - Format_version uint32 - Refcount int32 -} diff --git a/sdl/sdl.go b/sdl/sdl.go index 17dec8d..7fb75e4 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -23,15 +23,25 @@ type cast unsafe.Pointer var globalMutex sync.Mutex -// TODO: This should NOT be a public function, -// but since we need it in the package "ttf" ... the Go language is failing here -func Wrap(intSurface *InternalSurface) *Surface { +type Surface struct { + cSurface *C.SDL_Surface + mutex sync.RWMutex + + Flags uint32 + Format *PixelFormat + W int32 + H int32 + Pitch uint16 + Pixels unsafe.Pointer + Offset int32 +} + +func wrap(cSurface *C.SDL_Surface) *Surface { var s *Surface - if intSurface != nil { + if cSurface != nil { var surface Surface - surface.intSurface = intSurface - surface.reload() + surface.SetCSurface(unsafe.Pointer(cSurface)) s = &surface } else { s = nil @@ -40,20 +50,26 @@ func Wrap(intSurface *InternalSurface) *Surface { return s } -// Pull data from the internal-surface. Make sure to use this when -// the internal-surface might have been changed. +// FIXME: Ideally, this should NOT be a public function, but it is needed in the package "ttf" ... +func (s *Surface) SetCSurface(cSurface unsafe.Pointer) { + s.cSurface = (*C.SDL_Surface)(cSurface) + s.reload() +} + +// Pull data from C.SDL_Surface. +// Make sure to use this when the C surface might have been changed. func (s *Surface) reload() { - s.Flags = s.intSurface.Flags - s.Format = (*PixelFormat)(cast(s.intSurface.Format)) - s.W = s.intSurface.W - s.H = s.intSurface.H - s.Pitch = s.intSurface.Pitch - s.Pixels = s.intSurface.Pixels - s.Offset = s.intSurface.Offset + s.Flags = uint32(s.cSurface.flags) + s.Format = (*PixelFormat)(cast(s.cSurface.format)) + s.W = int32(s.cSurface.w) + s.H = int32(s.cSurface.h) + s.Pitch = uint16(s.cSurface.pitch) + s.Pixels = s.cSurface.pixels + s.Offset = int32(s.cSurface.offset) } func (s *Surface) destroy() { - s.intSurface = nil + s.cSurface = nil s.Format = nil s.Pixels = nil } @@ -164,7 +180,7 @@ var currentVideoSurface *Surface = nil func SetVideoMode(w int, h int, bpp int, flags uint32) *Surface { globalMutex.Lock() var screen = C.SDL_SetVideoMode(C.int(w), C.int(h), C.int(bpp), C.Uint32(flags)) - currentVideoSurface = Wrap((*InternalSurface)(cast(screen))) + currentVideoSurface = wrap(screen) globalMutex.Unlock() return currentVideoSurface } @@ -186,25 +202,41 @@ func VideoModeOK(width int, height int, bpp int, flags uint32) int { return status } +// Returns the list of available screen dimensions for the given format. +// +// NOTE: The result of this function uses a different encoding than the underlying C function. +// It returns an empty array if no modes are available, +// and nil if any dimension is okay for the given format. func ListModes(format *PixelFormat, flags uint32) []Rect { modes := C.SDL_ListModes((*C.SDL_PixelFormat)(cast(format)), C.Uint32(flags)) - if modes == nil { //no modes available + + // No modes available + if modes == nil { return make([]Rect, 0) } - var any int - *((***C.SDL_Rect)(unsafe.Pointer(&any))) = modes - if any == -1 { //any dimension is ok + + // (modes == -1) --> Any dimension is ok + if uintptr(unsafe.Pointer(modes))+1 == uintptr(0) { return nil } - var count int + count := 0 ptr := *modes //first element in the list - for count = 0; ptr != nil; count++ { + for ptr != nil { + count++ ptr = *(**C.SDL_Rect)(unsafe.Pointer(uintptr(unsafe.Pointer(modes)) + uintptr(count*unsafe.Sizeof(ptr)))) } - var ret = make([]Rect, count-1) - *((***C.SDL_Rect)(unsafe.Pointer(&ret))) = modes // TODO + ret := make([]Rect, count) + for i := 0; i < count; i++ { + ptr := (**C.SDL_Rect)(unsafe.Pointer(uintptr(unsafe.Pointer(modes)) + uintptr(i*unsafe.Sizeof(*modes)))) + var r *C.SDL_Rect = *ptr + ret[i].X = int16(r.x) + ret[i].Y = int16(r.y) + ret[i].W = uint16(r.w) + ret[i].H = uint16(r.h) + } + return ret } @@ -254,7 +286,7 @@ func (screen *Surface) UpdateRect(x int32, y int32, w uint32, h uint32) { globalMutex.Lock() screen.mutex.Lock() - C.SDL_UpdateRect((*C.SDL_Surface)(cast(screen.intSurface)), C.Sint32(x), C.Sint32(y), C.Uint32(w), C.Uint32(h)) + C.SDL_UpdateRect(screen.cSurface, C.Sint32(x), C.Sint32(y), C.Uint32(w), C.Uint32(h)) screen.mutex.Unlock() globalMutex.Unlock() @@ -265,7 +297,7 @@ func (screen *Surface) UpdateRects(rects []Rect) { globalMutex.Lock() screen.mutex.Lock() - C.SDL_UpdateRects((*C.SDL_Surface)(cast(screen.intSurface)), C.int(len(rects)), (*C.SDL_Rect)(cast(&rects[0]))) + C.SDL_UpdateRects(screen.cSurface, C.int(len(rects)), (*C.SDL_Rect)(cast(&rects[0]))) screen.mutex.Unlock() globalMutex.Unlock() @@ -303,7 +335,7 @@ func WM_SetCaption(title, icon string) { // Sets the icon for the display window. func WM_SetIcon(icon *Surface, mask *uint8) { globalMutex.Lock() - C.SDL_WM_SetIcon((*C.SDL_Surface)(cast(icon.intSurface)), (*C.Uint8)(mask)) + C.SDL_WM_SetIcon(icon.cSurface, (*C.Uint8)(mask)) globalMutex.Unlock() } @@ -318,7 +350,7 @@ func WM_IconifyWindow() int { // Toggles fullscreen mode func WM_ToggleFullScreen(surface *Surface) int { globalMutex.Lock() - status := int(C.SDL_WM_ToggleFullScreen((*C.SDL_Surface)(cast(surface.intSurface)))) + status := int(C.SDL_WM_ToggleFullScreen(surface.cSurface)) globalMutex.Unlock() return status } @@ -342,7 +374,7 @@ func (screen *Surface) Flip() int { globalMutex.Lock() screen.mutex.Lock() - status := int(C.SDL_Flip((*C.SDL_Surface)(cast(screen.intSurface)))) + status := int(C.SDL_Flip(screen.cSurface)) screen.mutex.Unlock() globalMutex.Unlock() @@ -355,7 +387,7 @@ func (screen *Surface) Free() { globalMutex.Lock() screen.mutex.Lock() - C.SDL_FreeSurface((*C.SDL_Surface)(cast(screen.intSurface))) + C.SDL_FreeSurface(screen.cSurface) screen.destroy() if screen == currentVideoSurface { @@ -369,7 +401,7 @@ func (screen *Surface) Free() { // Locks a surface for direct access. func (screen *Surface) Lock() int { screen.mutex.Lock() - status := int(C.SDL_LockSurface((*C.SDL_Surface)(cast(screen.intSurface)))) + status := int(C.SDL_LockSurface(screen.cSurface)) screen.mutex.Unlock() return status } @@ -377,7 +409,7 @@ func (screen *Surface) Lock() int { // Unlocks a previously locked surface. func (screen *Surface) Unlock() { screen.mutex.Lock() - C.SDL_UnlockSurface((*C.SDL_Surface)(cast(screen.intSurface))) + C.SDL_UnlockSurface(screen.cSurface) screen.mutex.Unlock() } @@ -386,9 +418,9 @@ func (dst *Surface) Blit(dstrect *Rect, src *Surface, srcrect *Rect) int { dst.mutex.Lock() var ret = C.SDL_UpperBlit( - (*C.SDL_Surface)(cast(src.intSurface)), + src.cSurface, (*C.SDL_Rect)(cast(srcrect)), - (*C.SDL_Surface)(cast(dst.intSurface)), + dst.cSurface, (*C.SDL_Rect)(cast(dstrect))) dst.mutex.Unlock() @@ -402,7 +434,7 @@ func (dst *Surface) FillRect(dstrect *Rect, color uint32) int { dst.mutex.Lock() var ret = C.SDL_FillRect( - (*C.SDL_Surface)(cast(dst.intSurface)), + dst.cSurface, (*C.SDL_Rect)(cast(dstrect)), C.Uint32(color)) @@ -414,7 +446,7 @@ func (dst *Surface) FillRect(dstrect *Rect, color uint32) int { // Adjusts the alpha properties of a Surface. func (s *Surface) SetAlpha(flags uint32, alpha uint8) int { s.mutex.Lock() - status := int(C.SDL_SetAlpha((*C.SDL_Surface)(cast(s.intSurface)), C.Uint32(flags), C.Uint8(alpha))) + status := int(C.SDL_SetAlpha(s.cSurface, C.Uint32(flags), C.Uint8(alpha))) s.mutex.Unlock() return status } @@ -422,24 +454,24 @@ func (s *Surface) SetAlpha(flags uint32, alpha uint8) int { // Sets the color key (transparent pixel) in a blittable surface and // enables or disables RLE blit acceleration. func (s *Surface) SetColorKey(flags uint32, ColorKey uint32) int { - return int(C.SDL_SetColorKey((*C.SDL_Surface)(cast(s)), - C.Uint32(flags), C.Uint32(ColorKey))) + s.mutex.Lock() + status := int(C.SDL_SetColorKey(s.cSurface, C.Uint32(flags), C.Uint32(ColorKey))) + s.mutex.Unlock() + return status } // Gets the clipping rectangle for a surface. func (s *Surface) GetClipRect(r *Rect) { s.mutex.RLock() - C.SDL_GetClipRect((*C.SDL_Surface)(cast(s.intSurface)), (*C.SDL_Rect)(cast(r))) + C.SDL_GetClipRect(s.cSurface, (*C.SDL_Rect)(cast(r))) s.mutex.RUnlock() - return } // Sets the clipping rectangle for a surface. func (s *Surface) SetClipRect(r *Rect) { s.mutex.Lock() - C.SDL_SetClipRect((*C.SDL_Surface)(cast(s.intSurface)), (*C.SDL_Rect)(cast(r))) + C.SDL_SetClipRect(s.cSurface, (*C.SDL_Rect)(cast(r))) s.mutex.Unlock() - return } // Map a RGBA color value to a pixel format. @@ -462,7 +494,7 @@ func Load(file string) *Surface { globalMutex.Unlock() - return Wrap((*InternalSurface)(cast(screen))) + return wrap(screen) } // Creates an empty Surface. @@ -474,15 +506,18 @@ func CreateRGBSurface(flags uint32, width int, height int, bpp int, Rmask uint32 globalMutex.Unlock() - return Wrap((*InternalSurface)(cast(p))) + return wrap(p) } // Converts a surface to the display format -func DisplayFormat(src *Surface) *Surface { - p := C.SDL_DisplayFormat((*C.SDL_Surface)(cast(src))) - return (*Surface)(cast(p)) +func (s *Surface) DisplayFormat() *Surface { + s.mutex.RLock() + p := C.SDL_DisplayFormat(s.cSurface) + s.mutex.RUnlock() + return wrap(p) } + // ======== // Keyboard // ======== @@ -583,6 +618,7 @@ func (event *Event) poll() bool { return ret != 0 } + // ===== // Mouse // ===== @@ -604,24 +640,6 @@ func GetRelativeMouseState(x, y *int) uint8 { return state } -// Returns ActiveEvent or nil if event has other type -func (event *Event) Active() *ActiveEvent { - if event.Type == ACTIVEEVENT { - return (*ActiveEvent)(cast(event)) - } - - return nil -} - -// Returns ResizeEvent or nil if event has other type -func (event *Event) Resize() *ResizeEvent { - if event.Type == VIDEORESIZE { - return (*ResizeEvent)(cast(event)) - } - - return nil -} - // Toggle whether or not the cursor is shown on the screen. func ShowCursor(toggle int) int { globalMutex.Lock() diff --git a/sdl/sdldraw.go b/sdl/sdldraw.go deleted file mode 100644 index fd1d182..0000000 --- a/sdl/sdldraw.go +++ /dev/null @@ -1,140 +0,0 @@ -package sdl - -//implementation of draw.Context and draw.Image interfaces - -import "exp/draw" -import "os" -import "image" -import "unsafe" -import "time" - -type Context struct { - screen *Surface - mouse_chan chan draw.Mouse - key_chan chan int - resize_chan chan bool - quit_chan chan bool -} - -func InitContext(w int, h int) (*Context, os.Error) { - - var this = new(Context) - - Init(INIT_VIDEO) - - this.screen = SetVideoMode(w, h, 32, SWSURFACE) - - this.screen.Lock() - - // TODO \/ - - this.resize_chan = make(chan bool, 64) - this.key_chan = make(chan int, 64) - this.mouse_chan = make(chan draw.Mouse, 1024) - this.quit_chan = make(chan bool) - - return this, nil - -} - -func (this *Context) Screen() draw.Image { return this.screen } - -func (this *Context) FlushImage() { - - this.screen.Unlock() - this.screen.Flip() - this.screen.Lock() - - e := &Event{} - - for e.Poll() { - switch e.Type { - case QUIT: - this.quit_chan <- true - break - case KEYDOWN: - this.key_chan <- int(e.Keyboard().Keysym.Sym) - break - case MOUSEBUTTONDOWN, MOUSEBUTTONUP: - m := e.MouseButton() - this.mouse_chan <- draw.Mouse{int(GetMouseState(nil, nil)), draw.Point{int(m.X), int(m.Y)}, time.Nanoseconds()} - break - case MOUSEMOTION: - m := e.MouseMotion() - this.mouse_chan <- draw.Mouse{int(GetMouseState(nil, nil)), draw.Point{int(m.X), int(m.Y)}, time.Nanoseconds()} - break - case VIDEORESIZE: - this.resize_chan <- true - break - default: - break - } - } - -} - -func (this *Context) KeyboardChan() <-chan int { - //TODO conversion - return this.key_chan -} - - -func (this *Context) MouseChan() <-chan draw.Mouse { - return this.mouse_chan -} - -func (this *Context) ResizeChan() <-chan bool { return this.resize_chan } -func (this *Context) QuitChan() <-chan bool { return this.quit_chan } - -// surface --> Image - -func (surface *Surface) ColorModel() image.ColorModel { - //TODO - return nil -} - -func (surface *Surface) Width() int { return int(surface.W) } - -func (surface *Surface) Height() int { return int(surface.H) } - -func (surface *Surface) Set(x, y int, c image.Color) { - //TODO endianess, bpp, alpha, etc - - var bpp = int(surface.Format.BytesPerPixel) - - var pixel = uintptr(unsafe.Pointer(surface.Pixels)) - - pixel += uintptr(y*int(surface.Pitch) + x*bpp) - - var p = (*image.RGBAColor)(unsafe.Pointer(pixel)) - - var r, g, b, a = c.RGBA() - - p.R = uint8(r) - p.G = uint8(g) - p.R = uint8(b) - p.A = uint8(255 - a) - -} - - -func (surface *Surface) At(x, y int) image.Color { - - var bpp = int(surface.Format.BytesPerPixel) - - var pixel = uintptr(unsafe.Pointer(surface.Pixels)) - - pixel += uintptr(y*int(surface.Pitch) + x*bpp) - - var color = *((*uint32)(unsafe.Pointer(pixel))) - - var r uint8 - var g uint8 - var b uint8 - var a uint8 - - GetRGBA(color, surface.Format, &r, &g, &b, &a) - - return image.RGBAColor{uint8(r), uint8(g), uint8(b), uint8(a)} - -} diff --git a/sdl/structs.6.go b/sdl/structs.6.go index 3b4ed93..9e2300a 100644 --- a/sdl/structs.6.go +++ b/sdl/structs.6.go @@ -1,29 +1,5 @@ package sdl -import "sync" - -type Surface struct { - intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) - mutex sync.RWMutex - Flags uint32 - Pad0 [4]byte - Format *PixelFormat - W int32 - H int32 - Pitch uint16 - Pad1 [6]byte - Pixels *byte - Offset int32 - Pad2 [4]byte - Hwdata *[0]byte /* sprivate_hwdata */ - Clip_rect Rect - Unused1 uint32 - Locked uint32 - Map *[0]byte /* sSDL_BlitMap */ - Format_version uint32 - Refcount int32 -} - type PixelFormat struct { Palette *Palette BitsPerPixel uint8 diff --git a/sdl/structs.8.go b/sdl/structs.8.go index b9b9bf7..647e810 100644 --- a/sdl/structs.8.go +++ b/sdl/structs.8.go @@ -1,27 +1,5 @@ package sdl -import "sync" - -type Surface struct { - intSurface *InternalSurface // TODO: InternalSurface should in fact be internalSurface (i.e: it should be non-public) - mutex sync.RWMutex - Flags uint32 - Format *PixelFormat - W int32 - H int32 - Pitch uint16 - Pad0 [2]byte - Pixels *byte - Offset int32 - Hwdata *[0]byte /* sprivate_hwdata */ - Clip_rect Rect - Unused1 uint32 - Locked uint32 - Map *[0]byte /* sSDL_BlitMap */ - Format_version uint32 - Refcount int32 -} - type PixelFormat struct { Palette *Palette BitsPerPixel uint8 diff --git a/test/Makefile b/test/Makefile index 4a5cdbc..4670fb3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.inc -TARG=⚛test +TARG=test GOFILES=test.go include $(GOROOT)/src/Make.cmd diff --git a/test/test.go b/test/test.go index 6710aa4..61eb635 100644 --- a/test/test.go +++ b/test/test.go @@ -152,7 +152,7 @@ func main() { println("") println(e.Keysym.Sym, ": ", sdl.GetKeyName(sdl.Key(e.Keysym.Sym))) - if e.Keyboard().Keysym.Sym == 27 { + if e.Keysym.Sym == sdl.K_ESCAPE { running = false } @@ -165,6 +165,7 @@ func main() { fmt.Printf("Type: %02x Which: %02x State: %02x Pad: %02x\n", e.Type, e.Which, e.State, e.Pad0[0]) fmt.Printf("Scancode: %02x Sym: %08x Mod: %04x Unicode: %04x\n", e.Keysym.Scancode, e.Keysym.Sym, e.Keysym.Mod, e.Keysym.Unicode) + case sdl.MouseButtonEvent: if e.Type == sdl.MOUSEBUTTONDOWN { println("Click:", e.X, e.Y) @@ -175,15 +176,6 @@ func main() { case sdl.ResizeEvent: println("resize screen ", e.W, e.H) - fmt.Printf("Type: %02x Which: %02x State: %02x Pad: %02x\n", k.Type, k.Which, k.State, k.Pad0[0]) - fmt.Printf("Scancode: %02x Sym: %08x Mod: %04x Unicode: %04x\n", k.Keysym.Scancode, k.Keysym.Sym, k.Keysym.Mod, k.Keysym.Unicode) - case sdl.MOUSEBUTTONDOWN: - println("Click:", e.MouseButton().X, e.MouseButton().Y) - in = out - out = make(chan Point) - go worm(in, out, draw) - case sdl.VIDEORESIZE: - println("resize screen ", e.Resize().W, e.Resize().H) screen = sdl.SetVideoMode(int(e.W), int(e.H), 32, sdl.RESIZABLE) diff --git a/ttf/ttf.go b/ttf/ttf.go index 3088754..06aff2c 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -12,6 +12,20 @@ import "C" import "⚛sdl" import "unsafe" +func wrap(cSurface *C.SDL_Surface) *sdl.Surface { + var s *sdl.Surface + + if cSurface != nil { + var surface sdl.Surface + surface.SetCSurface(unsafe.Pointer(cSurface)) + s = &surface + } else { + s = nil + } + + return s +} + // A ttf or otf font. type Font struct { cfont *C.TTF_Font @@ -63,7 +77,7 @@ func RenderText_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderText_Solid(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) + return wrap(surface) } // Renders UTF-8 text in the specified color and returns an SDL surface. Solid @@ -73,7 +87,7 @@ func RenderUTF8_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderUTF8_Solid(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) + return wrap(surface) } // Renders Latin-1 text in the specified color (and with the specified background @@ -85,7 +99,7 @@ func RenderText_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S cbgcol := C.SDL_Color{C.Uint8(bgcolor.R), C.Uint8(bgcolor.G), C.Uint8(bgcolor.B), C.Uint8(bgcolor.Unused)} surface := C.TTF_RenderText_Shaded(font.cfont, ctext, ccol, cbgcol) C.free(unsafe.Pointer(ctext)) - return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) + return wrap(surface) } // Renders UTF-8 text in the specified color (and with the specified background @@ -97,7 +111,7 @@ func RenderUTF8_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S cbgcol := C.SDL_Color{C.Uint8(bgcolor.R), C.Uint8(bgcolor.G), C.Uint8(bgcolor.B), C.Uint8(bgcolor.Unused)} surface := C.TTF_RenderUTF8_Shaded(font.cfont, ctext, ccol, cbgcol) C.free(unsafe.Pointer(ctext)) - return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) + return wrap(surface) } // Renders Latin-1 text in the specified color and returns an SDL surface. @@ -108,7 +122,7 @@ func RenderText_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderText_Blended(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) + return wrap(surface) } // Renders UTF-8 text in the specified color and returns an SDL surface. @@ -119,7 +133,7 @@ func RenderUTF8_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderUTF8_Blended(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) - return sdl.Wrap((*sdl.InternalSurface)(unsafe.Pointer(surface))) + return wrap(surface) } // Returns the rendering style of the font. From 19e117c06ca959e86b7ac7ba0d7e7510b61df387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sat, 18 Sep 2010 17:45:59 +0200 Subject: [PATCH 16/79] Minor fix when opening audio --- sdl/audio/audio.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 29acccc..d33aeed 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -53,10 +53,6 @@ type AudioSpec struct { } func OpenAudio(desired, obtained_orNil *AudioSpec) int { - mutex.Lock() - opened++ - mutex.Unlock() - var C_desired, C_obtained *C.SDL_AudioSpec C_desired = new(C.SDL_AudioSpec) @@ -76,6 +72,12 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { status := C.SDL_OpenAudio(C_desired, C_obtained) + if status == 0 { + mutex.Lock() + opened++ + mutex.Unlock() + } + if obtained_orNil != nil { obtained := obtained_orNil From 337b3e32d8ceba929f564f84fad0054be447b268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 16 Dec 2010 17:02:28 +0100 Subject: [PATCH 17/79] Update in response to Go release.2010-12-15.1 --- sdl/audio/Makefile | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile index ea0a39e..70bb179 100644 --- a/sdl/audio/Makefile +++ b/sdl/audio/Makefile @@ -1,24 +1,29 @@ include $(GOROOT)/src/Make.inc TARG=⚛sdl/audio +CALLBACK_LIB=sdl_audio_callback.so CGOFILES=audio.go -CGO_LDFLAGS=callback.o `pkg-config --libs sdl` +CGO_LDFLAGS=$(CALLBACK_LIB) `pkg-config --libs sdl` CGO_CFLAGS=`pkg-config --cflags sdl` +CGO_DEPS=$(CALLBACK_LIB) -include $(GOROOT)/src/Make.pkg +INSTALLFILES+=$(pkgdir)/$(CALLBACK_LIB) -_cgo_defun.c: $(CGOFILES) - CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) - sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c +include $(GOROOT)/src/Make.pkg _cgo_defun.c: callback.h -_obj/$(TARG).a: callback.o -_cgo_.so: callback.o +_obj/$(TARG).a: $(CALLBACK_LIB) callback.o: callback.c $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.c callback.o: callback.h + +$(CALLBACK_LIB): callback.o + $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(_CGO_LDFLAGS_$(GOOS)) + +$(pkgdir)/$(CALLBACK_LIB): $(CALLBACK_LIB) + cp $^ $@ From d5b06f9cda7274d4946dcebf1487c9d1c9c020d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 17 Dec 2010 13:36:03 +0100 Subject: [PATCH 18/79] Fix a race condition when closing SDL audio, add "-lrt" when linking a shared library --- sdl/audio/Makefile | 4 ++-- sdl/audio/audio.go | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile index 70bb179..b5d05cb 100644 --- a/sdl/audio/Makefile +++ b/sdl/audio/Makefile @@ -4,7 +4,7 @@ TARG=⚛sdl/audio CALLBACK_LIB=sdl_audio_callback.so CGOFILES=audio.go -CGO_LDFLAGS=$(CALLBACK_LIB) `pkg-config --libs sdl` +CGO_LDFLAGS=$(CALLBACK_LIB) `pkg-config --libs sdl` -lrt CGO_CFLAGS=`pkg-config --cflags sdl` CGO_DEPS=$(CALLBACK_LIB) @@ -23,7 +23,7 @@ callback.o: callback.c callback.o: callback.h $(CALLBACK_LIB): callback.o - $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(_CGO_LDFLAGS_$(GOOS)) + $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(_CGO_LDFLAGS_$(GOOS)) -lrt $(pkgdir)/$(CALLBACK_LIB): $(CALLBACK_LIB) cp $^ $@ diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index d33aeed..1f3ff40 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -93,6 +93,8 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { } func CloseAudio() { + PauseAudio(true) + mutex.Lock() { opened-- From 138094d076e46e9c26e0df467ed4ca1497e419e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sat, 18 Dec 2010 12:28:27 +0100 Subject: [PATCH 19/79] Remove a couple of lines obsoleted by Go release.2010-12-15 --- sdl/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sdl/Makefile b/sdl/Makefile index bad3334..921c294 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -13,7 +13,3 @@ include $(GOROOT)/src/Make.pkg constants.go: constants.c godefs -g sdl constants.c > constants.go gofmt -w constants.go - -_cgo_defun.c: $(CGOFILES) - CGOPKGPATH=$(dir) cgo -- $(CGO_CFLAGS) $(CGOFILES) - sed s/cgo_sdl/cgo_⚛sdl/ --in-place _cgo_defun.c From 9b938ebef9c37b52a2f261b213030f368fbae275 Mon Sep 17 00:00:00 2001 From: remogatto Date: Sun, 2 Jan 2011 16:50:18 +0100 Subject: [PATCH 20/79] Fix Keysym struct on AMD64 --- sdl/structs.6.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdl/structs.6.go b/sdl/structs.6.go index 9e2300a..0d8b1a3 100644 --- a/sdl/structs.6.go +++ b/sdl/structs.6.go @@ -164,9 +164,8 @@ type Event struct { } type Keysym struct { + Scancode uint8 Sym uint32 Mod uint32 Unicode uint16 - - Scancode uint8 // broken } From 5d4d2732a7ca17d024a1fc6c497ae59d57578fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sat, 8 Jan 2011 20:23:52 +0100 Subject: [PATCH 21/79] Minor adjustment to the "Keysym" structure in the x86-64 version --- .gitignore | 1 + sdl/sdl.go | 2 +- sdl/structs.6.go | 7 ++++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index e683b37..2960171 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ _obj test/test shoot.png *_cgo* +sdl_audio_callback.so diff --git a/sdl/sdl.go b/sdl/sdl.go index 7fb75e4..9440702 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -1,7 +1,7 @@ /* A binding of SDL and SDL_image. -The binding is works in pretty much the same way as it does in C, although +The binding works in pretty much the same way as it does in C, although some of the functions have been altered to give them an object-oriented flavor (eg. Rather than sdl.Flip(surface) it's surface.Flip() ) */ diff --git a/sdl/structs.6.go b/sdl/structs.6.go index 0d8b1a3..0c7a48a 100644 --- a/sdl/structs.6.go +++ b/sdl/structs.6.go @@ -165,7 +165,8 @@ type Event struct { type Keysym struct { Scancode uint8 - Sym uint32 - Mod uint32 - Unicode uint16 + Pad0 [3]byte + Sym uint32 + Mod uint32 + Unicode uint16 } From 9770d33bcadb99fb3b751fe1fecfb02a330fb5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 20 Jan 2011 20:17:19 +0100 Subject: [PATCH 22/79] Update in response to Go release.2011-01-20 (removal of the 'float' type) --- gfx/framerate.go | 8 ++++---- mixer/mixer.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gfx/framerate.go b/gfx/framerate.go index 1de8896..028e931 100644 --- a/gfx/framerate.go +++ b/gfx/framerate.go @@ -10,7 +10,7 @@ import ( type FPSmanager struct { framecount uint32 - rateticks float + rateticks float64 lastticks uint64 rate uint32 } @@ -19,7 +19,7 @@ func NewFramerate() *FPSmanager { return &FPSmanager{ framecount: 0, rate: FPS_DEFAULT, - rateticks: (1000.0 / float(FPS_DEFAULT)), + rateticks: (1000.0 / float64(FPS_DEFAULT)), lastticks: uint64(time.Nanoseconds()) / 1e6, } } @@ -28,7 +28,7 @@ func (manager *FPSmanager) SetFramerate(rate uint32) { if rate >= FPS_LOWER_LIMIT && rate <= FPS_UPPER_LIMIT { manager.framecount = 0 manager.rate = rate - manager.rateticks = 1000.0 / float(rate) + manager.rateticks = 1000.0 / float64(rate) } else { } } @@ -45,7 +45,7 @@ func (manager *FPSmanager) FramerateDelay() { // get/calc ticks current_ticks = uint64(time.Nanoseconds()) / 1e6 - target_ticks = manager.lastticks + uint64(float(manager.framecount)*manager.rateticks) + target_ticks = manager.lastticks + uint64(float64(manager.framecount)*manager.rateticks) if current_ticks <= target_ticks { the_delay = target_ticks - current_ticks diff --git a/mixer/mixer.go b/mixer/mixer.go index 8c7b96a..c8aff81 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -56,7 +56,7 @@ func (m *Music) FadeInMusic(loops, ms int) int { } // Same as FadeInMusic, only with a specified position to start the music at. -func (m *Music) FadeInMusicPos(loops, ms int, position float) int { +func (m *Music) FadeInMusicPos(loops, ms int, position float64) int { return int(C.Mix_FadeInMusicPos(m.cmusic, C.int(loops), C.int(ms), C.double(position))) } @@ -74,7 +74,7 @@ func ResumeMusic() { C.Mix_ResumeMusic() } func RewindMusic() { C.Mix_RewindMusic() } // Sets the position of the currently playing music. -func SetMusicPosition(position float) int { +func SetMusicPosition(position float64) int { return int(C.Mix_SetMusicPosition(C.double(position))) } From 1a867f66116c8ff08b5e62c9e40b334692f4194d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sun, 23 Jan 2011 11:54:45 +0100 Subject: [PATCH 23/79] Add thread-safety to TTF bindings --- README.md | 2 +- sdl/sdl.go | 154 +++++++++++++++++++------------------ ttf/ttf.go | 222 ++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 276 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 050097d..433d2a4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This is an improved version of Banthar's [Go-SDL](http://github.com/banthar/Go-S The improvements/differences are: -* SDL functions (maybe except for SDL-ttf) can be safely called from multiple concurrent goroutines +* SDL functions (except for SDL-mixer) can be safely called from multiple concurrent goroutines * All SDL events are delivered via a Go channel * Support for low-level SDL sound functions diff --git a/sdl/sdl.go b/sdl/sdl.go index 9440702..3496bff 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -21,7 +21,15 @@ import "sync" type cast unsafe.Pointer -var globalMutex sync.Mutex +// Mutex for serialization of access to certain SDL functions. +// +// There is no need to use this in application code, the mutex is a public variable +// just because it needs to be accessible from other parts of Go-SDL (such as package "sdl/ttf"). +// +// Surface-level functions (such as 'Surface.Blit') are not using this mutex, +// so it is possible to modify multiple surfaces concurrently. +// There is no dependency between 'Surface.Lock' and the global mutex. +var GlobalMutex sync.Mutex type Surface struct { cSurface *C.SDL_Surface @@ -93,15 +101,15 @@ func GoSdlVersion() string { // Initializes SDL. func Init(flags uint32) int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_Init(C.Uint32(flags))) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } // Shuts down SDL func Quit() { - globalMutex.Lock() + GlobalMutex.Lock() if currentVideoSurface != nil { currentVideoSurface.destroy() @@ -110,29 +118,29 @@ func Quit() { C.SDL_Quit() - globalMutex.Unlock() + GlobalMutex.Unlock() } // Initializes subsystems. func InitSubSystem(flags uint32) int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_InitSubSystem(C.Uint32(flags))) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } // Shuts down a subsystem. func QuitSubSystem(flags uint32) { - globalMutex.Lock() + GlobalMutex.Lock() C.SDL_QuitSubSystem(C.Uint32(flags)) - globalMutex.Unlock() + GlobalMutex.Unlock() } // Checks which subsystems are initialized. func WasInit(flags uint32) int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_WasInit(C.Uint32(flags))) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } @@ -143,28 +151,28 @@ func WasInit(flags uint32) int { // Gets SDL error string func GetError() string { - globalMutex.Lock() + GlobalMutex.Lock() s := C.GoString(C.SDL_GetError()) - globalMutex.Unlock() + GlobalMutex.Unlock() return s } // Set a string describing an error to be submitted to the SDL Error system. func SetError(description string) { - globalMutex.Lock() + GlobalMutex.Lock() cdescription := C.CString(description) C.SetError(cdescription) C.free(unsafe.Pointer(cdescription)) - globalMutex.Unlock() + GlobalMutex.Unlock() } // Clear the current SDL error func ClearError() { - globalMutex.Lock() + GlobalMutex.Lock() C.SDL_ClearError() - globalMutex.Unlock() + GlobalMutex.Unlock() } @@ -178,27 +186,27 @@ var currentVideoSurface *Surface = nil // returns a corresponding surface. You don't need to call the Free method // of the returned surface, as it will be done automatically by sdl.Quit. func SetVideoMode(w int, h int, bpp int, flags uint32) *Surface { - globalMutex.Lock() + GlobalMutex.Lock() var screen = C.SDL_SetVideoMode(C.int(w), C.int(h), C.int(bpp), C.Uint32(flags)) currentVideoSurface = wrap(screen) - globalMutex.Unlock() + GlobalMutex.Unlock() return currentVideoSurface } // Returns a pointer to the current display surface. func GetVideoSurface() *Surface { - globalMutex.Lock() + GlobalMutex.Lock() surface := currentVideoSurface - globalMutex.Unlock() + GlobalMutex.Unlock() return surface } // Checks to see if a particular video mode is supported. Returns 0 if not // supported, or the bits-per-pixel of the closest available mode. func VideoModeOK(width int, height int, bpp int, flags uint32) int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_VideoModeOK(C.int(width), C.int(height), C.int(bpp), C.Uint32(flags))) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } @@ -257,9 +265,9 @@ type VideoInfo struct { } func GetVideoInfo() *VideoInfo { - globalMutex.Lock() + GlobalMutex.Lock() vinfo := (*internalVideoInfo)(cast(C.SDL_GetVideoInfo())) - globalMutex.Unlock() + GlobalMutex.Unlock() flags := vinfo.Flags @@ -283,30 +291,30 @@ func GetVideoInfo() *VideoInfo { // Makes sure the given area is updated on the given screen. If x, y, w, and // h are all 0, the whole screen will be updated. func (screen *Surface) UpdateRect(x int32, y int32, w uint32, h uint32) { - globalMutex.Lock() + GlobalMutex.Lock() screen.mutex.Lock() C.SDL_UpdateRect(screen.cSurface, C.Sint32(x), C.Sint32(y), C.Uint32(w), C.Uint32(h)) screen.mutex.Unlock() - globalMutex.Unlock() + GlobalMutex.Unlock() } func (screen *Surface) UpdateRects(rects []Rect) { if len(rects) > 0 { - globalMutex.Lock() + GlobalMutex.Lock() screen.mutex.Lock() C.SDL_UpdateRects(screen.cSurface, C.int(len(rects)), (*C.SDL_Rect)(cast(&rects[0]))) screen.mutex.Unlock() - globalMutex.Unlock() + GlobalMutex.Unlock() } } // Gets the window title and icon name. func WM_GetCaption() (title, icon string) { - globalMutex.Lock() + GlobalMutex.Lock() // SDL seems to free these strings. TODO: Check to see if that's the case var ctitle, cicon *C.char @@ -314,7 +322,7 @@ func WM_GetCaption() (title, icon string) { title = C.GoString(ctitle) icon = C.GoString(cicon) - globalMutex.Unlock() + GlobalMutex.Unlock() return } @@ -324,9 +332,9 @@ func WM_SetCaption(title, icon string) { ctitle := C.CString(title) cicon := C.CString(icon) - globalMutex.Lock() + GlobalMutex.Lock() C.SDL_WM_SetCaption(ctitle, cicon) - globalMutex.Unlock() + GlobalMutex.Unlock() C.free(unsafe.Pointer(ctitle)) C.free(unsafe.Pointer(cicon)) @@ -334,57 +342,57 @@ func WM_SetCaption(title, icon string) { // Sets the icon for the display window. func WM_SetIcon(icon *Surface, mask *uint8) { - globalMutex.Lock() + GlobalMutex.Lock() C.SDL_WM_SetIcon(icon.cSurface, (*C.Uint8)(mask)) - globalMutex.Unlock() + GlobalMutex.Unlock() } // Minimizes the window func WM_IconifyWindow() int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_WM_IconifyWindow()) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } // Toggles fullscreen mode func WM_ToggleFullScreen(surface *Surface) int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_WM_ToggleFullScreen(surface.cSurface)) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } // Swaps OpenGL framebuffers/Update Display. func GL_SwapBuffers() { - globalMutex.Lock() + GlobalMutex.Lock() C.SDL_GL_SwapBuffers() - globalMutex.Unlock() + GlobalMutex.Unlock() } func GL_SetAttribute(attr int, value int) int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_GL_SetAttribute(C.SDL_GLattr(attr), C.int(value))) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } // Swaps screen buffers. func (screen *Surface) Flip() int { - globalMutex.Lock() + GlobalMutex.Lock() screen.mutex.Lock() status := int(C.SDL_Flip(screen.cSurface)) screen.mutex.Unlock() - globalMutex.Unlock() + GlobalMutex.Unlock() return status } // Frees (deletes) a Surface func (screen *Surface) Free() { - globalMutex.Lock() + GlobalMutex.Lock() screen.mutex.Lock() C.SDL_FreeSurface(screen.cSurface) @@ -395,7 +403,7 @@ func (screen *Surface) Free() { } screen.mutex.Unlock() - globalMutex.Unlock() + GlobalMutex.Unlock() } // Locks a surface for direct access. @@ -486,25 +494,25 @@ func GetRGBA(color uint32, format *PixelFormat, r, g, b, a *uint8) { // Loads Surface from file (using IMG_Load). func Load(file string) *Surface { - globalMutex.Lock() + GlobalMutex.Lock() cfile := C.CString(file) var screen = C.IMG_Load(cfile) C.free(unsafe.Pointer(cfile)) - globalMutex.Unlock() + GlobalMutex.Unlock() return wrap(screen) } // Creates an empty Surface. func CreateRGBSurface(flags uint32, width int, height int, bpp int, Rmask uint32, Gmask uint32, Bmask uint32, Amask uint32) *Surface { - globalMutex.Lock() + GlobalMutex.Lock() p := C.SDL_CreateRGBSurface(C.Uint32(flags), C.int(width), C.int(height), C.int(bpp), C.Uint32(Rmask), C.Uint32(Gmask), C.Uint32(Bmask), C.Uint32(Amask)) - globalMutex.Unlock() + GlobalMutex.Unlock() return wrap(p) } @@ -524,17 +532,17 @@ func (s *Surface) DisplayFormat() *Surface { // Enables UNICODE translation. func EnableUNICODE(enable int) int { - globalMutex.Lock() + GlobalMutex.Lock() previous := int(C.SDL_EnableUNICODE(C.int(enable))) - globalMutex.Unlock() + GlobalMutex.Unlock() return previous } // Sets keyboard repeat rate. func EnableKeyRepeat(delay, interval int) int { - globalMutex.Lock() + GlobalMutex.Lock() status := int(C.SDL_EnableKeyRepeat(C.int(delay), C.int(interval))) - globalMutex.Unlock() + GlobalMutex.Unlock() return status } @@ -543,16 +551,16 @@ func GetKeyRepeat() (int, int) { var delay int var interval int - globalMutex.Lock() + GlobalMutex.Lock() C.SDL_GetKeyRepeat((*C.int)(cast(&delay)), (*C.int)(cast(&interval))) - globalMutex.Unlock() + GlobalMutex.Unlock() return delay, interval } // Gets a snapshot of the current keyboard state func GetKeyState() []uint8 { - globalMutex.Lock() + GlobalMutex.Lock() var numkeys C.int array := C.SDL_GetKeyState(&numkeys) @@ -561,7 +569,7 @@ func GetKeyState() []uint8 { *((**C.Uint8)(unsafe.Pointer(&ptr))) = array // TODO - globalMutex.Unlock() + GlobalMutex.Unlock() return ptr @@ -575,24 +583,24 @@ type Key C.int // Gets the state of modifier keys func GetModState() Mod { - globalMutex.Lock() + GlobalMutex.Lock() state := Mod(C.SDL_GetModState()) - globalMutex.Unlock() + GlobalMutex.Unlock() return state } // Sets the state of modifier keys func SetModState(modstate Mod) { - globalMutex.Lock() + GlobalMutex.Lock() C.SDL_SetModState(C.SDLMod(modstate)) - globalMutex.Unlock() + GlobalMutex.Unlock() } // Gets the name of an SDL virtual keysym func GetKeyName(key Key) string { - globalMutex.Lock() + GlobalMutex.Lock() name := C.GoString(C.SDL_GetKeyName(C.SDLKey(key))) - globalMutex.Unlock() + GlobalMutex.Unlock() return name } @@ -603,7 +611,7 @@ func GetKeyName(key Key) string { // Polls for currently pending events func (event *Event) poll() bool { - globalMutex.Lock() + GlobalMutex.Lock() var ret = C.SDL_PollEvent((*C.SDL_Event)(cast(event))) @@ -613,7 +621,7 @@ func (event *Event) poll() bool { } } - globalMutex.Unlock() + GlobalMutex.Unlock() return ret != 0 } @@ -625,25 +633,25 @@ func (event *Event) poll() bool { // Retrieves the current state of the mouse. func GetMouseState(x, y *int) uint8 { - globalMutex.Lock() + GlobalMutex.Lock() state := uint8(C.SDL_GetMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) - globalMutex.Unlock() + GlobalMutex.Unlock() return state } // Retrieves the current state of the mouse relative to the last time this // function was called. func GetRelativeMouseState(x, y *int) uint8 { - globalMutex.Lock() + GlobalMutex.Lock() state := uint8(C.SDL_GetRelativeMouseState((*C.int)(cast(x)), (*C.int)(cast(y)))) - globalMutex.Unlock() + GlobalMutex.Unlock() return state } // Toggle whether or not the cursor is shown on the screen. func ShowCursor(toggle int) int { - globalMutex.Lock() + GlobalMutex.Lock() state := int(C.SDL_ShowCursor((C.int)(toggle))) - globalMutex.Unlock() + GlobalMutex.Unlock() return state } diff --git a/ttf/ttf.go b/ttf/ttf.go index 06aff2c..2ee6f15 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -10,8 +10,21 @@ package ttf // #include import "C" import "⚛sdl" +import "sync" import "unsafe" +// The version of Go-SDL TTF bindings. +// The version descriptor changes into a new unique string +// after a semantically incompatible Go-SDL update. +// +// The returned value can be checked by users of this package +// to make sure they are using a version with the expected semantics. +// +// If Go adds some kind of support for package versioning, this function will go away. +func GoSdlVersion() string { + return "⚛SDL TTF bindings 1.0" +} + func wrap(cSurface *C.SDL_Surface) *sdl.Surface { var s *sdl.Surface @@ -29,64 +42,109 @@ func wrap(cSurface *C.SDL_Surface) *sdl.Surface { // A ttf or otf font. type Font struct { cfont *C.TTF_Font + mutex sync.RWMutex } // Initializes SDL_ttf. -func Init() int { return int(C.TTF_Init()) } +func Init() int { + sdl.GlobalMutex.Lock() + status := int(C.TTF_Init()) + sdl.GlobalMutex.Unlock() + return status +} // Checks to see if SDL_ttf is initialized. Returns 1 if true, 0 if false. -func WasInit() int { return int(C.TTF_WasInit()) } +func WasInit() int { + sdl.GlobalMutex.Lock() + status := int(C.TTF_WasInit()) + sdl.GlobalMutex.Unlock() + return status +} // Shuts down SDL_ttf. -func Quit() { C.TTF_Quit() } +func Quit() { + sdl.GlobalMutex.Lock() + C.TTF_Quit() + sdl.GlobalMutex.Unlock() +} // Loads a font from a file at the specified point size. func OpenFont(file string, ptsize int) *Font { + sdl.GlobalMutex.Lock() + cfile := C.CString(file) cfont := C.TTF_OpenFont(cfile, C.int(ptsize)) C.free(unsafe.Pointer(cfile)) + sdl.GlobalMutex.Unlock() + if cfont == nil { return nil } - return &Font{cfont} + return &Font{cfont: cfont} } // Loads a font from a file containing multiple font faces at the specified // point size. func OpenFontIndex(file string, ptsize, index int) *Font { + sdl.GlobalMutex.Lock() + cfile := C.CString(file) cfont := C.TTF_OpenFontIndex(cfile, C.int(ptsize), C.long(index)) C.free(unsafe.Pointer(cfile)) + sdl.GlobalMutex.Unlock() + if cfont == nil { return nil } - return &Font{cfont} + return &Font{cfont: cfont} } // Frees the pointer to the font. -func (f *Font) Close() { C.TTF_CloseFont(f.cfont) } +func (f *Font) Close() { + sdl.GlobalMutex.Lock() + f.mutex.Lock() + + C.TTF_CloseFont(f.cfont) + + f.mutex.Unlock() + sdl.GlobalMutex.Unlock() +} // Renders Latin-1 text in the specified color and returns an SDL surface. Solid // rendering is quick, although not as smooth as the other rendering types. func RenderText_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { + sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderText_Solid(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) + + font.mutex.Unlock() + sdl.GlobalMutex.Unlock() + return wrap(surface) } // Renders UTF-8 text in the specified color and returns an SDL surface. Solid // rendering is quick, although not as smooth as the other rendering types. func RenderUTF8_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { + sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderUTF8_Solid(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) + + font.mutex.Unlock() + sdl.GlobalMutex.Unlock() + return wrap(surface) } @@ -94,11 +152,18 @@ func RenderUTF8_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { // color) and returns an SDL surface. Shaded rendering is slower than solid // rendering and the text is in a solid box, but it's better looking. func RenderText_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.Surface { + sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} cbgcol := C.SDL_Color{C.Uint8(bgcolor.R), C.Uint8(bgcolor.G), C.Uint8(bgcolor.B), C.Uint8(bgcolor.Unused)} surface := C.TTF_RenderText_Shaded(font.cfont, ctext, ccol, cbgcol) C.free(unsafe.Pointer(ctext)) + + font.mutex.Unlock() + sdl.GlobalMutex.Unlock() + return wrap(surface) } @@ -106,11 +171,18 @@ func RenderText_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S // color) and returns an SDL surface. Shaded rendering is slower than solid // rendering and the text is in a solid box, but it's better looking. func RenderUTF8_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.Surface { + sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} cbgcol := C.SDL_Color{C.Uint8(bgcolor.R), C.Uint8(bgcolor.G), C.Uint8(bgcolor.B), C.Uint8(bgcolor.Unused)} surface := C.TTF_RenderUTF8_Shaded(font.cfont, ctext, ccol, cbgcol) C.free(unsafe.Pointer(ctext)) + + font.mutex.Unlock() + sdl.GlobalMutex.Unlock() + return wrap(surface) } @@ -118,10 +190,17 @@ func RenderUTF8_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S // Blended rendering is the slowest of the three methods, although it produces // the best results, especially when blitted over another image. func RenderText_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { + sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderText_Blended(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) + + font.mutex.Unlock() + sdl.GlobalMutex.Unlock() + return wrap(surface) } @@ -129,65 +208,131 @@ func RenderText_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { // Blended rendering is the slowest of the three methods, although it produces // the best results, especially when blitted over another image. func RenderUTF8_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { + sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} surface := C.TTF_RenderUTF8_Blended(font.cfont, ctext, ccol) C.free(unsafe.Pointer(ctext)) + + font.mutex.Unlock() + sdl.GlobalMutex.Unlock() + return wrap(surface) } // Returns the rendering style of the font. -func (f *Font) GetStyle() int { return int(C.TTF_GetFontStyle(f.cfont)) } +func (f *Font) GetStyle() int { + f.mutex.RLock() + result := int(C.TTF_GetFontStyle(f.cfont)) + f.mutex.RUnlock() + return result +} // Sets the rendering style of the font. -func (f *Font) SetStyle(style int) { C.TTF_SetFontStyle(f.cfont, C.int(style)) } +func (f *Font) SetStyle(style int) { + sdl.GlobalMutex.Lock() + f.mutex.Lock() + + C.TTF_SetFontStyle(f.cfont, C.int(style)) + + f.mutex.Unlock() + sdl.GlobalMutex.Unlock() +} // Returns the maximum height of all the glyphs of the font. -func (f *Font) Height() int { return int(C.TTF_FontHeight(f.cfont)) } +func (f *Font) Height() int { + f.mutex.RLock() + result := int(C.TTF_FontHeight(f.cfont)) + f.mutex.RUnlock() + return result +} // Returns the maximum pixel ascent (from the baseline) of all the glyphs // of the font. -func (f *Font) Ascent() int { return int(C.TTF_FontAscent(f.cfont)) } +func (f *Font) Ascent() int { + f.mutex.RLock() + result := int(C.TTF_FontAscent(f.cfont)) + f.mutex.RUnlock() + return result +} // Returns the maximum pixel descent (from the baseline) of all the glyphs // of the font. -func (f *Font) Descent() int { return int(C.TTF_FontDescent(f.cfont)) } +func (f *Font) Descent() int { + f.mutex.RLock() + result := int(C.TTF_FontDescent(f.cfont)) + f.mutex.RUnlock() + return result +} // Returns the recommended pixel height of a rendered line of text. -func (f *Font) LineSkip() int { return int(C.TTF_FontLineSkip(f.cfont)) } +func (f *Font) LineSkip() int { + f.mutex.RLock() + result := int(C.TTF_FontLineSkip(f.cfont)) + f.mutex.RUnlock() + return result +} // Returns the number of available faces (sub-fonts) in the font. -func (f *Font) Faces() int { return int(C.TTF_FontFaces(f.cfont)) } +func (f *Font) Faces() int { + f.mutex.RLock() + result := int(C.TTF_FontFaces(f.cfont)) + f.mutex.RUnlock() + return result +} // Returns >0 if the font's currently selected face is fixed width // (i.e. monospace), 0 if not. -func (f *Font) IsFixedWidth() int { return int(C.TTF_FontFaceIsFixedWidth(f.cfont)) } +func (f *Font) IsFixedWidth() int { + f.mutex.RLock() + result := int(C.TTF_FontFaceIsFixedWidth(f.cfont)) + f.mutex.RUnlock() + return result +} // Returns the family name of the font's currently selected face, // or a blank string if unavailable. func (f *Font) FamilyName() string { - if f == nil { - return "nil" - } - p := C.TTF_FontFaceFamilyName(f.cfont) - if p == nil { - return "" + var s string + if f != nil { + f.mutex.RLock() + + p := C.TTF_FontFaceFamilyName(f.cfont) + if p != nil { + s = C.GoString(p) + } else { + s = "" + } + + f.mutex.RUnlock() + } else { + s = "nil" } - s := C.GoString(p) + return s } // Returns the style name of the font's currently selected face, // or a blank string if unavailable. func (f *Font) StyleName() string { - if f == nil { - return "nil" - } - p := C.TTF_FontFaceStyleName(f.cfont) - if p == nil { - return "" + var s string + if f != nil { + f.mutex.RLock() + + p := C.TTF_FontFaceStyleName(f.cfont) + if p != nil { + s = C.GoString(p) + } else { + s = "" + } + + f.mutex.RUnlock() + } else { + s = "nil" } - s := C.GoString(p) + return s } @@ -202,12 +347,19 @@ func (f *Font) StyleName() string { // For more information on glyph metrics, visit // http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html func (f *Font) GlyphMetrics(ch uint16) (int, int, int, int, int, int) { + sdl.GlobalMutex.Lock() // Because the underlying C code is fairly complex + f.mutex.Lock() // Use a write lock, because 'C.TTF_GlyphMetrics' may update font's internal caches + minx := C.int(0) maxx := C.int(0) miny := C.int(0) maxy := C.int(0) advance := C.int(0) err := C.TTF_GlyphMetrics(f.cfont, C.Uint16(ch), &minx, &maxx, &miny, &maxy, &advance) + + sdl.GlobalMutex.Unlock() + f.mutex.Unlock() + return int(minx), int(maxx), int(miny), int(maxy), int(advance), int(err) } @@ -215,10 +367,17 @@ func (f *Font) GlyphMetrics(ch uint16) (int, int, int, int, int, int) { // // Return values are (width, height, err) where err is 0 for success, -1 on any error. func (f *Font) SizeText(text string) (int, int, int) { + sdl.GlobalMutex.Lock() // Because the underlying C code is fairly complex + f.mutex.Lock() // Use a write lock, because 'C.TTF_Size*' may update its internal cache + w := C.int(0) h := C.int(0) s := C.CString(text) err := C.TTF_SizeText(f.cfont, s, &w, &h) + + sdl.GlobalMutex.Unlock() + f.mutex.Unlock() + return int(w), int(h), int(err) } @@ -226,9 +385,16 @@ func (f *Font) SizeText(text string) (int, int, int) { // // Return values are (width, height, err) where err is 0 for success, -1 on any error. func (f *Font) SizeUTF8(text string) (int, int, int) { + sdl.GlobalMutex.Lock() // Because the underlying C code is fairly complex + f.mutex.Lock() // Use a write lock, because 'C.TTF_Size*' may update font's internal caches + w := C.int(0) h := C.int(0) s := C.CString(text) err := C.TTF_SizeUTF8(f.cfont, s, &w, &h) + + sdl.GlobalMutex.Unlock() + f.mutex.Unlock() + return int(w), int(h), int(err) } From 4f1165745d837f9362d86cc3c6b5978676255704 Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Mon, 24 Jan 2011 11:37:15 +0100 Subject: [PATCH 24/79] Add support for joystick devices --- sdl/constants.c | 12 +++- sdl/constants.go | 9 +++ sdl/event.go | 6 ++ sdl/sdl.go | 172 +++++++++++++++++++++++++++++++++++++++++++++++ sdl/structs.8.go | 20 ++++++ test/test.go | 29 +++++++- 6 files changed, 246 insertions(+), 2 deletions(-) diff --git a/sdl/constants.c b/sdl/constants.c index b8f4af5..2bdaa16 100644 --- a/sdl/constants.c +++ b/sdl/constants.c @@ -350,6 +350,16 @@ enum $KMOD_MODE = KMOD_MODE, $KMOD_RESERVED = KMOD_RESERVED, - +// hat states + + $HAT_CENTERED = SDL_HAT_CENTERED, + $HAT_UP = SDL_HAT_UP, + $HAT_RIGHT = SDL_HAT_RIGHT, + $HAT_DOWN = SDL_HAT_DOWN, + $HAT_LEFT = SDL_HAT_LEFT, + $HAT_RIGHTUP = SDL_HAT_RIGHTUP, + $HAT_RIGHTDOWN = SDL_HAT_RIGHTDOWN, + $HAT_LEFTUP = SDL_HAT_LEFTUP, + $HAT_LEFTDOWN = SDL_HAT_LEFTDOWN, }; diff --git a/sdl/constants.go b/sdl/constants.go index 0fae0ec..0451906 100644 --- a/sdl/constants.go +++ b/sdl/constants.go @@ -331,6 +331,15 @@ const ( KMOD_CAPS = 0x2000 KMOD_MODE = 0x4000 KMOD_RESERVED = 0x8000 + HAT_CENTERED = 0 + HAT_UP = 0x1 + HAT_RIGHT = 0x2 + HAT_DOWN = 0x4 + HAT_LEFT = 0x8 + HAT_RIGHTUP = 0x3 + HAT_RIGHTDOWN = 0x6 + HAT_LEFTUP = 0x9 + HAT_LEFTDOWN = 0xc ) // Types diff --git a/sdl/event.go b/sdl/event.go index 5e73a79..2015f34 100644 --- a/sdl/event.go +++ b/sdl/event.go @@ -35,6 +35,12 @@ func pollEvents() { case MOUSEMOTION: events <- *(*MouseMotionEvent)(cast(event)) + case JOYAXISMOTION: + events <- *(*JoyAxisEvent)(cast(event)) + + case JOYBUTTONDOWN, JOYBUTTONUP: + events <- *(*JoyButtonEvent)(cast(event)) + case ACTIVEEVENT: events <- *(*ActiveEvent)(cast(event)) diff --git a/sdl/sdl.go b/sdl/sdl.go index 3496bff..4a302e6 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -655,3 +655,175 @@ func ShowCursor(toggle int) int { GlobalMutex.Unlock() return state } + +// ======== +// Joystick +// ======== + +type Joystick struct { + cJoystick *C.SDL_Joystick + mutex sync.RWMutex +} + +func (j *Joystick) setCJoystick(cJoystick unsafe.Pointer) { + j.cJoystick = (*C.SDL_Joystick)(cJoystick) +} + +func wrapJoystick(cJoystick *C.SDL_Joystick) *Joystick { + var j *Joystick + if cJoystick != nil { + var joystick Joystick + joystick.setCJoystick(unsafe.Pointer(cJoystick)) + j = &joystick + } else { + j = nil + } + return j +} + +// Count the number of joysticks attached to the system +func NumJoysticks() int { + GlobalMutex.Lock() + num := int(C.SDL_NumJoysticks()) + GlobalMutex.Unlock() + return num +} + +// Get the implementation dependent name of a joystick. +// This can be called before any joysticks are opened. +// If no name can be found, this function returns NULL. +func JoystickName(deviceIndex int) string { + GlobalMutex.Lock() + name := C.GoString(C.SDL_JoystickName(C.int(deviceIndex))) + GlobalMutex.Unlock() + return name +} + +// Open a joystick for use The index passed as an argument refers to +// the N'th joystick on the system. This index is the value which will +// identify this joystick in future joystick events. This function +// returns a joystick identifier, or NULL if an error occurred. +func JoystickOpen(deviceIndex int) *Joystick { + GlobalMutex.Lock() + joystick := C.SDL_JoystickOpen(C.int(deviceIndex)) + GlobalMutex.Unlock() + return wrapJoystick(joystick) +} + + +// Returns 1 if the joystick has been opened, or 0 if it has not. +func JoystickOpened(deviceIndex int) int { + GlobalMutex.Lock() + opened := int(C.SDL_JoystickOpened(C.int(deviceIndex))) + GlobalMutex.Unlock() + return opened +} + +// Update the current state of the open joysticks. This is called +// automatically by the event loop if any joystick events are enabled. +func JoystickUpdate() { + GlobalMutex.Lock() + C.SDL_JoystickUpdate() + GlobalMutex.Unlock() +} + +// Enable/disable joystick event polling. If joystick events are +// disabled, you must call SDL_JoystickUpdate() yourself and check the +// state of the joystick when you want joystick information. The state +// can be one of SDL_QUERY, SDL_ENABLE or SDL_IGNORE. +func JoystickEventState(state int) int { + GlobalMutex.Lock() + result := int(C.SDL_JoystickEventState(C.int(state))) + GlobalMutex.Unlock() + return result +} + +// Get the number of general axis controls on a joystick +func (joystick *Joystick) NumAxes() int { + joystick.mutex.RLock() + num := int(C.SDL_JoystickNumAxes(joystick.cJoystick)) + joystick.mutex.RUnlock() + return num +} + +// Get the device index of an opened joystick. +func (joystick *Joystick) Index() int { + joystick.mutex.RLock() + index := int(C.SDL_JoystickIndex(joystick.cJoystick)) + joystick.mutex.RUnlock() + return index +} + +// Get the number of buttons on a joystick +func (joystick *Joystick) NumButtons() int { + joystick.mutex.RLock() + num := int(C.SDL_JoystickNumButtons(joystick.cJoystick)) + joystick.mutex.RUnlock() + return num +} + +// Get the number of trackballs on a Joystick trackballs have only +// relative motion events associated with them and their state cannot +// be polled. +func (joystick *Joystick) NumBalls() int { + joystick.mutex.RLock() + num := int(C.SDL_JoystickNumBalls(joystick.cJoystick)) + joystick.mutex.RUnlock() + return num +} + +// Get the number of POV hats on a joystick +func (joystick *Joystick) NumHats() int { + joystick.mutex.RLock() + num := int(C.SDL_JoystickNumHats(joystick.cJoystick)) + joystick.mutex.RUnlock() + return num +} + +// Get the current state of a POV hat on a joystick +// The hat indices start at index 0. +func (joystick *Joystick) GetHat(hat int) uint8 { + joystick.mutex.RLock() + state := uint8(C.SDL_JoystickGetHat(joystick.cJoystick, C.int(hat))) + joystick.mutex.RUnlock() + return state +} + +// Close a joystick previously opened with SDL_JoystickOpen() +func (joystick *Joystick) Close() { + joystick.mutex.Lock() + C.SDL_JoystickClose(joystick.cJoystick) + joystick.mutex.Unlock() +} + +// Get the current state of a button on a joystick. The button indices +// start at index 0. +func (joystick *Joystick) GetButton(button int) uint8 { + joystick.mutex.RLock() + state := uint8(C.SDL_JoystickGetButton(joystick.cJoystick, C.int(button))) + joystick.mutex.RUnlock() + return state +} + +// Get the ball axis change since the last poll. The ball indices +// start at index 0.This returns 0, or -1 if you passed it invalid +// parameters. +func (joystick *Joystick) GetBall(ball int, dx, dy *int) int { + joystick.mutex.RLock() + state := int(C.SDL_JoystickGetBall(joystick.cJoystick, C.int(ball), (*C.int)(cast(dx)), (*C.int)(cast(dy)))) + joystick.mutex.RUnlock() + return state +} + + +// Get the current state of an axis control on a joystick. The axis +// indices start at index 0. The state is a value ranging from -32768 +// to 32767. +func (joystick *Joystick) GetAxis(axis int) int16 { + joystick.mutex.RLock() + state := int16(C.SDL_JoystickGetAxis(joystick.cJoystick, C.int(axis))) + joystick.mutex.RUnlock() + return state +} + + diff --git a/sdl/structs.8.go b/sdl/structs.8.go index 647e810..b72a195 100644 --- a/sdl/structs.8.go +++ b/sdl/structs.8.go @@ -169,3 +169,23 @@ type Keysym struct { Mod uint32 Unicode uint16 } + +type BallDelta struct { + Dx int + Dy int +} + +// type Joystick struct { +// Index uint8 // Device index +// Name *int8 // Joystick name - system dependent +// Naxes int // Number of axis controls on the joystick +// Axes *int16 // Current axis states +// Nhats int // Number of hats on the joystick +// Hats *uint8 // Current hat states +// Nballs int // Number of trackballs on the joystick +// Balls *BallDelta // Current ball motion deltas +// Nbuttons int // Number of buttons on the joystick +// Buttons *uint8 // Current button states +// Hwdata *[0]byte // Driver dependent information +// Ref_count int // Reference count for multiple opens +// } diff --git a/test/test.go b/test/test.go index 61eb635..be6b6c3 100644 --- a/test/test.go +++ b/test/test.go @@ -41,7 +41,7 @@ func worm(in <-chan Point, out chan<- Point, draw chan<- Point) { } func main() { - + var joy *sdl.Joystick if sdl.Init(sdl.INIT_EVERYTHING) != 0 { panic(sdl.GetError()) } @@ -50,6 +50,21 @@ func main() { panic(sdl.GetError()) } + if sdl.NumJoysticks() > 0 { + // Open joystick + joy = sdl.JoystickOpen(0) + + if joy != nil { + println("Opened Joystick 0") + println("Name: ", sdl.JoystickName(0)) + println("Number of Axes: ", joy.NumAxes()) + println("Number of Buttons: ", joy.NumButtons()) + println("Number of Balls: ", joy.NumBalls()) + } else { + println("Couldn't open Joystick!"); + } + } + if mixer.OpenAudio(mixer.DEFAULT_FREQUENCY, mixer.DEFAULT_FORMAT, mixer.DEFAULT_CHANNELS, 4096) != 0 { panic(sdl.GetError()) @@ -174,6 +189,13 @@ func main() { go worm(in, out, draw) } + case sdl.JoyAxisEvent: + println("Joystick Axis Event ->", "Type", e.Type, "Axis:", e.Axis, " Value:", e.Value, "Which:", e.Which) + + case sdl.JoyButtonEvent: + println("Joystick Button Event ->", e.Button) + println("State of button", e.Button, "->", joy.GetButton(int(e.Button))) + case sdl.ResizeEvent: println("resize screen ", e.W, e.H) @@ -186,6 +208,11 @@ func main() { } } + // Close if opened + if(sdl.JoystickOpened(0) > 0) { + joy.Close() + } + image.Free() music.Free() font.Close() From ad9bf9e404dd9e5767c0758d40ddef4850082644 Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Mon, 24 Jan 2011 13:26:42 +0100 Subject: [PATCH 25/79] Add BallDelta struct to structs.6.go --- sdl/structs.6.go | 5 +++++ sdl/structs.8.go | 15 --------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/sdl/structs.6.go b/sdl/structs.6.go index 0c7a48a..cafb87f 100644 --- a/sdl/structs.6.go +++ b/sdl/structs.6.go @@ -170,3 +170,8 @@ type Keysym struct { Mod uint32 Unicode uint16 } + +type BallDelta struct { + Dx int + Dy int +} diff --git a/sdl/structs.8.go b/sdl/structs.8.go index b72a195..a23d75b 100644 --- a/sdl/structs.8.go +++ b/sdl/structs.8.go @@ -174,18 +174,3 @@ type BallDelta struct { Dx int Dy int } - -// type Joystick struct { -// Index uint8 // Device index -// Name *int8 // Joystick name - system dependent -// Naxes int // Number of axis controls on the joystick -// Axes *int16 // Current axis states -// Nhats int // Number of hats on the joystick -// Hats *uint8 // Current hat states -// Nballs int // Number of trackballs on the joystick -// Balls *BallDelta // Current ball motion deltas -// Nbuttons int // Number of buttons on the joystick -// Buttons *uint8 // Current button states -// Hwdata *[0]byte // Driver dependent information -// Ref_count int // Reference count for multiple opens -// } From 69bdd7048590a220c370a1bb60b730d33fea9b2d Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Mon, 24 Jan 2011 13:26:42 +0100 Subject: [PATCH 26/79] Restore previous structs.*.go files. --- sdl/structs.6.go | 5 +++++ sdl/structs.8.go | 15 --------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/sdl/structs.6.go b/sdl/structs.6.go index 0c7a48a..cafb87f 100644 --- a/sdl/structs.6.go +++ b/sdl/structs.6.go @@ -170,3 +170,8 @@ type Keysym struct { Mod uint32 Unicode uint16 } + +type BallDelta struct { + Dx int + Dy int +} diff --git a/sdl/structs.8.go b/sdl/structs.8.go index b72a195..a23d75b 100644 --- a/sdl/structs.8.go +++ b/sdl/structs.8.go @@ -174,18 +174,3 @@ type BallDelta struct { Dx int Dy int } - -// type Joystick struct { -// Index uint8 // Device index -// Name *int8 // Joystick name - system dependent -// Naxes int // Number of axis controls on the joystick -// Axes *int16 // Current axis states -// Nhats int // Number of hats on the joystick -// Hats *uint8 // Current hat states -// Nballs int // Number of trackballs on the joystick -// Balls *BallDelta // Current ball motion deltas -// Nbuttons int // Number of buttons on the joystick -// Buttons *uint8 // Current button states -// Hwdata *[0]byte // Driver dependent information -// Ref_count int // Reference count for multiple opens -// } From b97d31dc96443daf20f57e96e78006c083192ffe Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Mon, 24 Jan 2011 13:41:18 +0100 Subject: [PATCH 27/79] Remove BallDelta from structs.*.go. --- sdl/structs.6.go | 5 ----- sdl/structs.8.go | 5 ----- 2 files changed, 10 deletions(-) diff --git a/sdl/structs.6.go b/sdl/structs.6.go index cafb87f..0c7a48a 100644 --- a/sdl/structs.6.go +++ b/sdl/structs.6.go @@ -170,8 +170,3 @@ type Keysym struct { Mod uint32 Unicode uint16 } - -type BallDelta struct { - Dx int - Dy int -} diff --git a/sdl/structs.8.go b/sdl/structs.8.go index a23d75b..647e810 100644 --- a/sdl/structs.8.go +++ b/sdl/structs.8.go @@ -169,8 +169,3 @@ type Keysym struct { Mod uint32 Unicode uint16 } - -type BallDelta struct { - Dx int - Dy int -} From db06a17c40a4d488624bf654663db18404e4aaad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 26 Jan 2011 09:37:31 +0100 Subject: [PATCH 28/79] Fix internal comments --- ttf/ttf.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ttf/ttf.go b/ttf/ttf.go index 2ee6f15..b318634 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -118,7 +118,7 @@ func (f *Font) Close() { // rendering is quick, although not as smooth as the other rendering types. func RenderText_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' - font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's internal caches ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} @@ -135,7 +135,7 @@ func RenderText_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { // rendering is quick, although not as smooth as the other rendering types. func RenderUTF8_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' - font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's internal caches ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} @@ -153,7 +153,7 @@ func RenderUTF8_Solid(font *Font, text string, color sdl.Color) *sdl.Surface { // rendering and the text is in a solid box, but it's better looking. func RenderText_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.Surface { sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' - font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's internal caches ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} @@ -172,7 +172,7 @@ func RenderText_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S // rendering and the text is in a solid box, but it's better looking. func RenderUTF8_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.Surface { sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' - font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's internal caches ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} @@ -191,7 +191,7 @@ func RenderUTF8_Shaded(font *Font, text string, color, bgcolor sdl.Color) *sdl.S // the best results, especially when blitted over another image. func RenderText_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' - font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's internal caches ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} @@ -209,7 +209,7 @@ func RenderText_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { // the best results, especially when blitted over another image. func RenderUTF8_Blended(font *Font, text string, color sdl.Color) *sdl.Surface { sdl.GlobalMutex.Lock() // Because 'C.TTF_Render*' uses 'C.SDL_CreateRGBSurface' - font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's its internal caches + font.mutex.Lock() // Use a write lock, because 'C.TTF_Render*' may update font's internal caches ctext := C.CString(text) ccol := C.SDL_Color{C.Uint8(color.R), C.Uint8(color.G), C.Uint8(color.B), C.Uint8(color.Unused)} @@ -368,7 +368,7 @@ func (f *Font) GlyphMetrics(ch uint16) (int, int, int, int, int, int) { // Return values are (width, height, err) where err is 0 for success, -1 on any error. func (f *Font) SizeText(text string) (int, int, int) { sdl.GlobalMutex.Lock() // Because the underlying C code is fairly complex - f.mutex.Lock() // Use a write lock, because 'C.TTF_Size*' may update its internal cache + f.mutex.Lock() // Use a write lock, because 'C.TTF_Size*' may update font's internal cache w := C.int(0) h := C.int(0) From 58be877a5626a3647a18bf58aa1a96e915d8ff83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 26 Jan 2011 09:54:17 +0100 Subject: [PATCH 29/79] Remove per-joystick locking (the underlying C code does not need it), use the global lock when closing a joystick, run gofmt --- sdl/sdl.go | 73 ++++++++++++++-------------------------------------- test/test.go | 13 +++++----- 2 files changed, 26 insertions(+), 60 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index 4a302e6..3d4dac8 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -656,24 +656,20 @@ func ShowCursor(toggle int) int { return state } + // ======== // Joystick // ======== type Joystick struct { cJoystick *C.SDL_Joystick - mutex sync.RWMutex -} - -func (j *Joystick) setCJoystick(cJoystick unsafe.Pointer) { - j.cJoystick = (*C.SDL_Joystick)(cJoystick) } func wrapJoystick(cJoystick *C.SDL_Joystick) *Joystick { var j *Joystick if cJoystick != nil { var joystick Joystick - joystick.setCJoystick(unsafe.Pointer(cJoystick)) + joystick.cJoystick = (*C.SDL_Joystick)(unsafe.Pointer(cJoystick)) j = &joystick } else { j = nil @@ -710,7 +706,6 @@ func JoystickOpen(deviceIndex int) *Joystick { return wrapJoystick(joystick) } - // Returns 1 if the joystick has been opened, or 0 if it has not. func JoystickOpened(deviceIndex int) int { GlobalMutex.Lock() @@ -738,92 +733,62 @@ func JoystickEventState(state int) int { return result } +// Close a joystick previously opened with SDL_JoystickOpen() +func (joystick *Joystick) Close() { + GlobalMutex.Lock() + C.SDL_JoystickClose(joystick.cJoystick) + GlobalMutex.Unlock() +} + // Get the number of general axis controls on a joystick func (joystick *Joystick) NumAxes() int { - joystick.mutex.RLock() - num := int(C.SDL_JoystickNumAxes(joystick.cJoystick)) - joystick.mutex.RUnlock() - return num + return int(C.SDL_JoystickNumAxes(joystick.cJoystick)) } // Get the device index of an opened joystick. func (joystick *Joystick) Index() int { - joystick.mutex.RLock() - index := int(C.SDL_JoystickIndex(joystick.cJoystick)) - joystick.mutex.RUnlock() - return index + return int(C.SDL_JoystickIndex(joystick.cJoystick)) } // Get the number of buttons on a joystick func (joystick *Joystick) NumButtons() int { - joystick.mutex.RLock() - num := int(C.SDL_JoystickNumButtons(joystick.cJoystick)) - joystick.mutex.RUnlock() - return num + return int(C.SDL_JoystickNumButtons(joystick.cJoystick)) } // Get the number of trackballs on a Joystick trackballs have only // relative motion events associated with them and their state cannot // be polled. func (joystick *Joystick) NumBalls() int { - joystick.mutex.RLock() - num := int(C.SDL_JoystickNumBalls(joystick.cJoystick)) - joystick.mutex.RUnlock() - return num + return int(C.SDL_JoystickNumBalls(joystick.cJoystick)) } // Get the number of POV hats on a joystick func (joystick *Joystick) NumHats() int { - joystick.mutex.RLock() - num := int(C.SDL_JoystickNumHats(joystick.cJoystick)) - joystick.mutex.RUnlock() - return num + return int(C.SDL_JoystickNumHats(joystick.cJoystick)) } // Get the current state of a POV hat on a joystick // The hat indices start at index 0. func (joystick *Joystick) GetHat(hat int) uint8 { - joystick.mutex.RLock() - state := uint8(C.SDL_JoystickGetHat(joystick.cJoystick, C.int(hat))) - joystick.mutex.RUnlock() - return state -} - -// Close a joystick previously opened with SDL_JoystickOpen() -func (joystick *Joystick) Close() { - joystick.mutex.Lock() - C.SDL_JoystickClose(joystick.cJoystick) - joystick.mutex.Unlock() + return uint8(C.SDL_JoystickGetHat(joystick.cJoystick, C.int(hat))) } // Get the current state of a button on a joystick. The button indices // start at index 0. func (joystick *Joystick) GetButton(button int) uint8 { - joystick.mutex.RLock() - state := uint8(C.SDL_JoystickGetButton(joystick.cJoystick, C.int(button))) - joystick.mutex.RUnlock() - return state + return uint8(C.SDL_JoystickGetButton(joystick.cJoystick, C.int(button))) } // Get the ball axis change since the last poll. The ball indices -// start at index 0.This returns 0, or -1 if you passed it invalid +// start at index 0. This returns 0, or -1 if you passed it invalid // parameters. func (joystick *Joystick) GetBall(ball int, dx, dy *int) int { - joystick.mutex.RLock() - state := int(C.SDL_JoystickGetBall(joystick.cJoystick, C.int(ball), (*C.int)(cast(dx)), (*C.int)(cast(dy)))) - joystick.mutex.RUnlock() - return state + return int(C.SDL_JoystickGetBall(joystick.cJoystick, C.int(ball), (*C.int)(cast(dx)), (*C.int)(cast(dy)))) } - // Get the current state of an axis control on a joystick. The axis // indices start at index 0. The state is a value ranging from -32768 // to 32767. func (joystick *Joystick) GetAxis(axis int) int16 { - joystick.mutex.RLock() - state := int16(C.SDL_JoystickGetAxis(joystick.cJoystick, C.int(axis))) - joystick.mutex.RUnlock() - return state + return int16(C.SDL_JoystickGetAxis(joystick.cJoystick, C.int(axis))) } - - diff --git a/test/test.go b/test/test.go index be6b6c3..fc32b5c 100644 --- a/test/test.go +++ b/test/test.go @@ -53,7 +53,7 @@ func main() { if sdl.NumJoysticks() > 0 { // Open joystick joy = sdl.JoystickOpen(0) - + if joy != nil { println("Opened Joystick 0") println("Name: ", sdl.JoystickName(0)) @@ -61,7 +61,7 @@ func main() { println("Number of Buttons: ", joy.NumButtons()) println("Number of Balls: ", joy.NumBalls()) } else { - println("Couldn't open Joystick!"); + println("Couldn't open Joystick!") } } @@ -129,7 +129,7 @@ func main() { out = make(chan Point) go worm(in, out, draw) - ticker := time.NewTicker(1e9/50 /*50Hz*/) + ticker := time.NewTicker(1e9 / 50 /*50Hz*/ ) // Note: The following SDL code is highly ineffective. // It is eating too much CPU. If you intend to use Go-SDL, @@ -141,7 +141,8 @@ func main() { screen.FillRect(nil, 0x302019) screen.Blit(&sdl.Rect{0, 0, 0, 0}, text, nil) - loop: for { + loop: + for { select { case p := <-draw: screen.Blit(&sdl.Rect{int16(p.x), int16(p.y), 0, 0}, image, nil) @@ -194,7 +195,7 @@ func main() { case sdl.JoyButtonEvent: println("Joystick Button Event ->", e.Button) - println("State of button", e.Button, "->", joy.GetButton(int(e.Button))) + println("State of button", e.Button, "->", joy.GetButton(int(e.Button))) case sdl.ResizeEvent: println("resize screen ", e.W, e.H) @@ -209,7 +210,7 @@ func main() { } // Close if opened - if(sdl.JoystickOpened(0) > 0) { + if sdl.JoystickOpened(0) > 0 { joy.Close() } From aebe60ff9bf2a67587112a6303ea628af4e62399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 21 Feb 2011 21:32:34 +0100 Subject: [PATCH 30/79] If required, lock the main video surface while blitting (this enables to call 'sdl.Surface.Blit' from one goroutine and 'sdl.SetVideoMode' from another goroutine, while the two goroutines are allowed to execute in parallel, without requiring a mutex in the two goroutines) --- sdl/sdl.go | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index 3d4dac8..99bfd85 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -422,18 +422,35 @@ func (screen *Surface) Unlock() { } func (dst *Surface) Blit(dstrect *Rect, src *Surface, srcrect *Rect) int { - src.mutex.RLock() - dst.mutex.Lock() - - var ret = C.SDL_UpperBlit( - src.cSurface, - (*C.SDL_Rect)(cast(srcrect)), - dst.cSurface, - (*C.SDL_Rect)(cast(dstrect))) - - dst.mutex.Unlock() - src.mutex.RUnlock() + GlobalMutex.Lock() + global := true + if (src != currentVideoSurface) && (dst != currentVideoSurface) { + GlobalMutex.Unlock() + global = false + } + + // At this point: GlobalMutex is locked only if at least one of 'src' or 'dst' + // was identical to 'currentVideoSurface' + + var ret C.int + { + src.mutex.RLock() + dst.mutex.Lock() + + ret = C.SDL_UpperBlit( + src.cSurface, + (*C.SDL_Rect)(cast(srcrect)), + dst.cSurface, + (*C.SDL_Rect)(cast(dstrect))) + + dst.mutex.Unlock() + src.mutex.RUnlock() + } + if global { + GlobalMutex.Unlock() + } + return int(ret) } From 626e80106ae3f00df51416a0785a77e3671bb5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 25 Feb 2011 18:08:49 +0100 Subject: [PATCH 31/79] Update in response to Go release.2011-02-24, run gofmt --- gfx/constants.go | 6 +++--- sdl/audio/Makefile | 20 ++------------------ sdl/sdl.go | 8 ++++---- 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/gfx/constants.go b/gfx/constants.go index e6be30e..db90ba1 100644 --- a/gfx/constants.go +++ b/gfx/constants.go @@ -1,7 +1,7 @@ package gfx const ( - FPS_UPPER_LIMIT = 200 - FPS_LOWER_LIMIT = 1 - FPS_DEFAULT = 30 + FPS_UPPER_LIMIT = 200 + FPS_LOWER_LIMIT = 1 + FPS_DEFAULT = 30 ) diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile index b5d05cb..4cb5769 100644 --- a/sdl/audio/Makefile +++ b/sdl/audio/Makefile @@ -1,29 +1,13 @@ include $(GOROOT)/src/Make.inc TARG=⚛sdl/audio -CALLBACK_LIB=sdl_audio_callback.so CGOFILES=audio.go -CGO_LDFLAGS=$(CALLBACK_LIB) `pkg-config --libs sdl` -lrt +CGO_LDFLAGS=`pkg-config --libs sdl` -lrt CGO_CFLAGS=`pkg-config --cflags sdl` -CGO_DEPS=$(CALLBACK_LIB) - -INSTALLFILES+=$(pkgdir)/$(CALLBACK_LIB) +CGO_OFILES=callback.o include $(GOROOT)/src/Make.pkg _cgo_defun.c: callback.h - - -_obj/$(TARG).a: $(CALLBACK_LIB) - -callback.o: callback.c - $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.c - callback.o: callback.h - -$(CALLBACK_LIB): callback.o - $(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(_CGO_LDFLAGS_$(GOOS)) -lrt - -$(pkgdir)/$(CALLBACK_LIB): $(CALLBACK_LIB) - cp $^ $@ diff --git a/sdl/sdl.go b/sdl/sdl.go index 99bfd85..655fdff 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -428,15 +428,15 @@ func (dst *Surface) Blit(dstrect *Rect, src *Surface, srcrect *Rect) int { GlobalMutex.Unlock() global = false } - + // At this point: GlobalMutex is locked only if at least one of 'src' or 'dst' // was identical to 'currentVideoSurface' - + var ret C.int { src.mutex.RLock() dst.mutex.Lock() - + ret = C.SDL_UpperBlit( src.cSurface, (*C.SDL_Rect)(cast(srcrect)), @@ -450,7 +450,7 @@ func (dst *Surface) Blit(dstrect *Rect, src *Surface, srcrect *Rect) int { if global { GlobalMutex.Unlock() } - + return int(ret) } From 52520e7c5411064cc1514109f142a6d43455b8b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Tue, 2 Aug 2011 14:48:47 +0200 Subject: [PATCH 32/79] Update in response to Go release r59, add support for some forgotten joystick events --- Makefile | 1 + sdl/audio/audio.go | 8 ++++---- sdl/event.go | 9 ++++++++- sdl/sdl.go | 4 ++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index c89e062..cd6f924 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ include $(GOROOT)/src/Make.inc all: install install: + make clean make -C sdl install make -C sdl/audio install make -C ttf install diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 1f3ff40..366bcf5 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -171,7 +171,7 @@ func UnlockAudio() { // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_int16(data []int16) { if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) } } @@ -179,7 +179,7 @@ func SendAudio_int16(data []int16) { // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_uint16(data []uint16) { if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) } } @@ -187,7 +187,7 @@ func SendAudio_uint16(data []uint16) { // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_int8(data []int8) { if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) } } @@ -195,7 +195,7 @@ func SendAudio_int8(data []int8) { // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_uint8(data []uint8) { if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(unsafe.Sizeof(data[0])*len(data))) + sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) } } diff --git a/sdl/event.go b/sdl/event.go index 2015f34..a21e2ca 100644 --- a/sdl/event.go +++ b/sdl/event.go @@ -7,7 +7,8 @@ var events chan interface{} = make(chan interface{}) // This channel delivers SDL events. Each object received from this channel // has one of the following types: sdl.QuitEvent, sdl.KeyboardEvent, // sdl.MouseButtonEvent, sdl.MouseMotionEvent, sdl.ActiveEvent, -// sdl.ResizeEvent. +// sdl.ResizeEvent, sdl.JoyAxisEvent, sdl.JoyButtonEvent, sdl.JoyHatEvent, +// sdl.JoyBallEvent var Events <-chan interface{} = events // Polling interval, in milliseconds @@ -41,6 +42,12 @@ func pollEvents() { case JOYBUTTONDOWN, JOYBUTTONUP: events <- *(*JoyButtonEvent)(cast(event)) + case JOYHATMOTION: + events <- *(*JoyHatEvent)(cast(event)) + + case JOYBALLMOTION: + events <- *(*JoyBallEvent)(cast(event)) + case ACTIVEEVENT: events <- *(*ActiveEvent)(cast(event)) diff --git a/sdl/sdl.go b/sdl/sdl.go index 655fdff..28f50d2 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -232,12 +232,12 @@ func ListModes(format *PixelFormat, flags uint32) []Rect { ptr := *modes //first element in the list for ptr != nil { count++ - ptr = *(**C.SDL_Rect)(unsafe.Pointer(uintptr(unsafe.Pointer(modes)) + uintptr(count*unsafe.Sizeof(ptr)))) + ptr = *(**C.SDL_Rect)(unsafe.Pointer(uintptr(unsafe.Pointer(modes)) + uintptr(count*int(unsafe.Sizeof(ptr))))) } ret := make([]Rect, count) for i := 0; i < count; i++ { - ptr := (**C.SDL_Rect)(unsafe.Pointer(uintptr(unsafe.Pointer(modes)) + uintptr(i*unsafe.Sizeof(*modes)))) + ptr := (**C.SDL_Rect)(unsafe.Pointer(uintptr(unsafe.Pointer(modes)) + uintptr(i*int(unsafe.Sizeof(*modes))))) var r *C.SDL_Rect = *ptr ret[i].X = int16(r.x) ret[i].Y = int16(r.y) From d2fdc5734f0c4d58dcddfa87371303c552492d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sun, 20 Nov 2011 17:21:23 +0100 Subject: [PATCH 33/79] =?UTF-8?q?Use=20atom/sdl=20instead=20of=20=E2=9A=9B?= =?UTF-8?q?sdl=20as=20import=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 4s/4s.go | 2 +- README.md | 2 +- doc/template.go | 2 +- gfx/Makefile | 2 +- mixer/Makefile | 2 +- sdl/Makefile | 2 +- sdl/audio/Makefile | 2 +- test/test.go | 6 +++--- ttf/Makefile | 2 +- ttf/ttf.go | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/4s/4s.go b/4s/4s.go index f44976b..03a8af6 100644 --- a/4s/4s.go +++ b/4s/4s.go @@ -8,7 +8,7 @@ package main import ( - "⚛sdl" + "atom/sdl" "log" "os" "runtime" diff --git a/README.md b/README.md index 433d2a4..9738d52 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The improvements/differences are: * Support for low-level SDL sound functions * Can be installed in parallel to Banthar's Go-SDL -* The import path is "⚛sdl", instead of "sdl" +* The import path is "atom/sdl", instead of "sdl" # Installation diff --git a/doc/template.go b/doc/template.go index 6f8c962..ef6ac1c 100644 --- a/doc/template.go +++ b/doc/template.go @@ -1,7 +1,7 @@ package main import ( - "⚛sdl" + "atom/sdl" "fmt" "rand" "time" diff --git a/gfx/Makefile b/gfx/Makefile index 6a79896..4fafc8c 100644 --- a/gfx/Makefile +++ b/gfx/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.inc -TARG=⚛sdl/gfx +TARG=atom/sdl/gfx GOFILES:=constants.go\ framerate.go diff --git a/mixer/Makefile b/mixer/Makefile index 1dd7828..09054ee 100644 --- a/mixer/Makefile +++ b/mixer/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.inc -TARG=⚛sdl/mixer +TARG=atom/sdl/mixer GOFILES:=constants.go CGOFILES:=mixer.go diff --git a/sdl/Makefile b/sdl/Makefile index 921c294..6ce42e9 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -1,6 +1,6 @@ include $(GOROOT)/src/Make.inc -TARG=⚛sdl +TARG=atom/sdl GOFILES:=constants.go event.go structs.$(O).go diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile index 4cb5769..1e06efc 100644 --- a/sdl/audio/Makefile +++ b/sdl/audio/Makefile @@ -1,6 +1,6 @@ include $(GOROOT)/src/Make.inc -TARG=⚛sdl/audio +TARG=atom/sdl/audio CGOFILES=audio.go CGO_LDFLAGS=`pkg-config --libs sdl` -lrt diff --git a/test/test.go b/test/test.go index fc32b5c..0a04c74 100644 --- a/test/test.go +++ b/test/test.go @@ -1,9 +1,9 @@ package main import ( - "⚛sdl" - "⚛sdl/ttf" - "⚛sdl/mixer" + "atom/sdl" + "atom/sdl/ttf" + "atom/sdl/mixer" "math" "fmt" "time" diff --git a/ttf/Makefile b/ttf/Makefile index 35c474a..2443ca4 100644 --- a/ttf/Makefile +++ b/ttf/Makefile @@ -4,7 +4,7 @@ include $(GOROOT)/src/Make.inc -TARG=⚛sdl/ttf +TARG=atom/sdl/ttf GOFILES:=constants.go CGOFILES:=ttf.go diff --git a/ttf/ttf.go b/ttf/ttf.go index b318634..b6b1e7d 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -9,7 +9,7 @@ package ttf // #include import "C" -import "⚛sdl" +import "atom/sdl" import "sync" import "unsafe" From ab77a7461b5343b2e205b19a584eeb351959c9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 9 Dec 2011 18:07:27 +0100 Subject: [PATCH 34/79] Remove dependency on CLOCK_MONOTONIC in callback.c --- sdl/audio/callback.c | 78 ++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/sdl/audio/callback.c b/sdl/audio/callback.c index c6cde14..1ac0531 100644 --- a/sdl/audio/callback.c +++ b/sdl/audio/callback.c @@ -10,11 +10,13 @@ #include #include #include -#include #define TRUE 1 #define FALSE 0 +// Uncomment the next line to enable debugging messages +//#define DEBUG + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t need = PTHREAD_COND_INITIALIZER; static pthread_cond_t avail = PTHREAD_COND_INITIALIZER; @@ -23,6 +25,8 @@ static size_t available = 0; // Number of bytes available (from the pro static Uint8 *stream; // Communication buffer between the consumer and the producer +#ifdef DEBUG +#include static int64_t get_time() { struct timespec ts; if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) @@ -30,9 +34,12 @@ static int64_t get_time() { else return -1; } +#endif +#ifdef DEBUG static uint64_t cummulativeLatency = 0; static unsigned numCallbacks = 0; +#endif static void SDLCALL callback(void *userdata, Uint8 *_stream, int _len) { assert(_len > 0); @@ -45,34 +52,43 @@ static void SDLCALL callback(void *userdata, Uint8 *_stream, int _len) { stream = _stream; { - int64_t t1 = get_time(); - //printf("consumer: t1=%lld µs\n", (long long)t1/1000); + #ifdef DEBUG + int64_t t1 = get_time(); + printf("consumer: t1=%lld µs\n", (long long)t1/1000); + #endif assert(needed == 0); - //printf("consumer: needed <- %zu\n", len); + #ifdef DEBUG + printf("consumer: needed <- %zu\n", len); + #endif needed = len; pthread_cond_signal(&need); - //printf("consumer: waiting for data\n"); + #ifdef DEBUG + printf("consumer: waiting for data\n"); + #endif pthread_cond_wait(&avail, &m); assert(needed == 0); assert(available == len); - int64_t t2 = get_time(); - //printf("consumer: t2=%lld µs\n", (long long)t2/1000); - if(t1>0 && t2>0) { - uint64_t latency = t2-t1; - cummulativeLatency += latency; - numCallbacks++; - /*printf("consumer: latency=%lld µs, avg=%u µs\n", - (long long)(latency/1000), - (unsigned)(cummulativeLatency/numCallbacks/1000));*/ - } + #ifdef DEBUG + int64_t t2 = get_time(); + printf("consumer: t2=%lld µs\n", (long long)t2/1000); + if(t1>0 && t2>0) { + uint64_t latency = t2-t1; + cummulativeLatency += latency; + numCallbacks++; + printf("consumer: latency=%lld µs, avg=%u µs\n", + (long long)(latency/1000), + (unsigned)(cummulativeLatency/numCallbacks/1000)); + } + #endif } - //printf("consumer: received %zu bytes of data\n", available); - - //printf("consumer: available <- 0\n"); + #ifdef DEBUG + printf("consumer: received %zu bytes of data\n", available); + printf("consumer: available <- 0\n"); + #endif available = 0; stream = NULL; } @@ -89,16 +105,22 @@ void callback_fillBuffer(Uint8 *data, size_t numBytes) { pthread_mutex_lock(&m); while(sent < numBytes) { - //int64_t t = get_time(); - //printf("producer: t=%lld µs\n", (long long)t1/1000); + #ifdef DEBUG + int64_t t = get_time(); + printf("producer: t=%lld µs\n", (long long)t/1000); + #endif if(needed == 0) { - //printf("producer: waiting until data is needed (1)\n"); + #ifdef DEBUG + printf("producer: waiting until data is needed (1)\n"); + #endif pthread_cond_wait(&need, &m); // Interrupted from 'callback_unblock' ? if(needed == 0) { - //printf("producer: interrupted (1)\n"); + #ifdef DEBUG + printf("producer: interrupted (1)\n"); + #endif break; } } @@ -113,17 +135,23 @@ void callback_fillBuffer(Uint8 *data, size_t numBytes) { sent += n; needed -= n; - //printf("producer: added %zu bytes, available=%zu\n", n, available); + #ifdef DEBUG + printf("producer: added %zu bytes, available=%zu\n", n, available); + #endif if(needed == 0) { pthread_cond_signal(&avail); if(sent < numBytes) { - //printf("producer: waiting until data is needed (2)\n"); + #ifdef DEBUG + printf("producer: waiting until data is needed (2)\n"); + #endif pthread_cond_wait(&need, &m); // Interrupted from 'callback_unblock' ? if(needed == 0) { - //printf("producer: interrupted (2)\n"); + #ifdef DEBUG + printf("producer: interrupted (2)\n"); + #endif break; } } From 33ecb9679d36471eac1f6c07252d2427c5bae398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 9 Dec 2011 20:36:40 +0100 Subject: [PATCH 35/79] Use -lpthread instead of -lrt on Windows --- sdl/audio/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile index 1e06efc..378e7a6 100644 --- a/sdl/audio/Makefile +++ b/sdl/audio/Makefile @@ -3,10 +3,15 @@ include $(GOROOT)/src/Make.inc TARG=atom/sdl/audio CGOFILES=audio.go -CGO_LDFLAGS=`pkg-config --libs sdl` -lrt CGO_CFLAGS=`pkg-config --cflags sdl` CGO_OFILES=callback.o +ifeq ($(GOOS),windows) +CGO_LDFLAGS=`pkg-config --libs sdl` -lpthread +else +CGO_LDFLAGS=`pkg-config --libs sdl` -lrt +endif + include $(GOROOT)/src/Make.pkg _cgo_defun.c: callback.h From 0a164ce7f145aef200158a23c2d0671a05e4c9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 12 Dec 2011 12:36:42 +0100 Subject: [PATCH 36/79] Use gomake in Makefile, move "pkg-config ..." from Makefiles to Go files --- Makefile | 35 +++++++++++++++++++++-------------- mixer/Makefile | 1 - mixer/mixer.go | 1 + sdl/Makefile | 3 --- sdl/audio/Makefile | 5 ++--- sdl/audio/audio.go | 1 + sdl/sdl.go | 2 ++ ttf/ttf.go | 1 + 8 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index cd6f924..a4a3328 100644 --- a/Makefile +++ b/Makefile @@ -7,19 +7,26 @@ include $(GOROOT)/src/Make.inc all: install install: - make clean - make -C sdl install - make -C sdl/audio install - make -C ttf install - make -C mixer install - make -C gfx install + gomake clean + gomake -C sdl install + gomake -C sdl/audio install + gomake -C ttf install + gomake -C mixer install + gomake -C gfx install clean: - make -C sdl clean - make -C sdl/audio clean - make -C ttf clean - make -C mixer clean - make -C 4s clean - make -C test clean - make -C gfx clean - make -C doc clean + gomake -C sdl clean + gomake -C sdl/audio clean + gomake -C ttf clean + gomake -C mixer clean + gomake -C 4s clean + gomake -C test clean + gomake -C gfx clean + gomake -C doc clean + +nuke: + gomake -C sdl nuke + gomake -C sdl/audio nuke + gomake -C ttf nuke + gomake -C mixer nuke + gomake -C gfx nuke diff --git a/mixer/Makefile b/mixer/Makefile index 09054ee..2623857 100644 --- a/mixer/Makefile +++ b/mixer/Makefile @@ -8,7 +8,6 @@ TARG=atom/sdl/mixer GOFILES:=constants.go CGOFILES:=mixer.go -CGO_LDFLAGS:=-lSDL_mixer CLEANFILES+=mixer diff --git a/mixer/mixer.go b/mixer/mixer.go index c8aff81..4f3728e 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -7,6 +7,7 @@ functions have been changed to be in a more object-oriented style */ package mixer +// #cgo pkg-config: SDL_mixer // #include import "C" import "unsafe" diff --git a/sdl/Makefile b/sdl/Makefile index 6ce42e9..3ae6b64 100644 --- a/sdl/Makefile +++ b/sdl/Makefile @@ -3,10 +3,7 @@ include $(GOROOT)/src/Make.inc TARG=atom/sdl GOFILES:=constants.go event.go structs.$(O).go - CGOFILES:=sdl.go -CGO_LDFLAGS:=`pkg-config --libs sdl` -lSDL_image -CGO_CFLAGS:=`pkg-config --cflags sdl` include $(GOROOT)/src/Make.pkg diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile index 378e7a6..512ef33 100644 --- a/sdl/audio/Makefile +++ b/sdl/audio/Makefile @@ -3,13 +3,12 @@ include $(GOROOT)/src/Make.inc TARG=atom/sdl/audio CGOFILES=audio.go -CGO_CFLAGS=`pkg-config --cflags sdl` CGO_OFILES=callback.o ifeq ($(GOOS),windows) -CGO_LDFLAGS=`pkg-config --libs sdl` -lpthread +CGO_LDFLAGS=-lpthread else -CGO_LDFLAGS=`pkg-config --libs sdl` -lrt +CGO_LDFLAGS=-lrt endif include $(GOROOT)/src/Make.pkg diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 366bcf5..a6dbcb1 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -7,6 +7,7 @@ package audio +// #cgo pkg-config: sdl // #include // #include "callback.h" import "C" diff --git a/sdl/sdl.go b/sdl/sdl.go index 28f50d2..f14e39f 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -8,6 +8,8 @@ flavor (eg. Rather than sdl.Flip(surface) it's surface.Flip() ) package sdl +// #cgo pkg-config: sdl SDL_image +// // struct private_hwdata{}; // struct SDL_BlitMap{}; // #define map _map diff --git a/ttf/ttf.go b/ttf/ttf.go index b6b1e7d..68bf6b8 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -7,6 +7,7 @@ that work with loaded fonts are changed to have a more object-oriented feel. */ package ttf +// #cgo pkg-config: SDL_ttf // #include import "C" import "atom/sdl" From 8f320bebfe96452c0e6a01e1d33d50bb2c3ad88a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 12 Dec 2011 13:02:59 +0100 Subject: [PATCH 37/79] Add SDL_GL_* constants (patch suggested by https://github.com/cjyar) --- sdl/constants.c | 20 ++ sdl/constants.go | 685 ++++++++++++++++++++++++----------------------- 2 files changed, 371 insertions(+), 334 deletions(-) diff --git a/sdl/constants.c b/sdl/constants.c index 2bdaa16..307f8ff 100644 --- a/sdl/constants.c +++ b/sdl/constants.c @@ -41,6 +41,26 @@ enum $LOGPAL = SDL_LOGPAL, $PHYSPAL = SDL_PHYSPAL, +// More setvideo flags: GLattr enumeration + + $GL_RED_SIZE = SDL_GL_RED_SIZE, + $GL_GREEN_SIZE = SDL_GL_GREEN_SIZE, + $GL_BLUE_SIZE = SDL_GL_BLUE_SIZE, + $GL_ALPHA_SIZE = SDL_GL_ALPHA_SIZE, + $GL_BUFFER_SIZE = SDL_GL_BUFFER_SIZE, + $GL_DOUBLEBUFFER = SDL_GL_DOUBLEBUFFER, + $GL_DEPTH_SIZE = SDL_GL_DEPTH_SIZE, + $GL_STENCIL_SIZE = SDL_GL_STENCIL_SIZE, + $GL_ACCUM_RED_SIZE = SDL_GL_ACCUM_RED_SIZE, + $GL_ACCUM_GREEN_SIZE = SDL_GL_ACCUM_GREEN_SIZE, + $GL_ACCUM_BLUE_SIZE = SDL_GL_ACCUM_BLUE_SIZE, + $GL_ACCUM_ALPHA_SIZE = SDL_GL_ACCUM_ALPHA_SIZE, + $GL_STEREO = SDL_GL_STEREO, + $GL_MULTISAMPLEBUFFERS = SDL_GL_MULTISAMPLEBUFFERS, + $GL_MULTISAMPLESAMPLES = SDL_GL_MULTISAMPLESAMPLES, + $GL_ACCELERATED_VISUAL = SDL_GL_ACCELERATED_VISUAL, + $GL_SWAP_CONTROL = SDL_GL_SWAP_CONTROL, + // event types $NOEVENT = SDL_NOEVENT, diff --git a/sdl/constants.go b/sdl/constants.go index 0451906..98848e1 100644 --- a/sdl/constants.go +++ b/sdl/constants.go @@ -6,340 +6,357 @@ package sdl // Constants const ( - INIT_AUDIO = 0x10 - INIT_VIDEO = 0x20 - INIT_CDROM = 0x100 - INIT_TIMER = 0x1 - INIT_JOYSTICK = 0x200 - INIT_NOPARACHUTE = 0x100000 - INIT_EVENTTHREAD = 0x1000000 - INIT_EVERYTHING = 0xffff - SWSURFACE = 0 - HWSURFACE = 0x1 - ASYNCBLIT = 0x4 - ANYFORMAT = 0x10000000 - HWPALETTE = 0x20000000 - DOUBLEBUF = 0x40000000 - FULLSCREEN = 0x80000000 - OPENGL = 0x2 - OPENGLBLIT = 0xa - RESIZABLE = 0x10 - NOFRAME = 0x20 - HWACCEL = 0x100 - SRCCOLORKEY = 0x1000 - RLEACCELOK = 0x2000 - RLEACCEL = 0x4000 - SRCALPHA = 0x10000 - PREALLOC = 0x1000000 - YV12_OVERLAY = 0x32315659 - IYUV_OVERLAY = 0x56555949 - YUY2_OVERLAY = 0x32595559 - UYVY_OVERLAY = 0x59565955 - YVYU_OVERLAY = 0x55595659 - LOGPAL = 0x1 - PHYSPAL = 0x2 - NOEVENT = 0 - ACTIVEEVENT = 0x1 - KEYDOWN = 0x2 - KEYUP = 0x3 - MOUSEMOTION = 0x4 - MOUSEBUTTONDOWN = 0x5 - MOUSEBUTTONUP = 0x6 - JOYAXISMOTION = 0x7 - JOYBALLMOTION = 0x8 - JOYHATMOTION = 0x9 - JOYBUTTONDOWN = 0xa - JOYBUTTONUP = 0xb - QUIT = 0xc - SYSWMEVENT = 0xd - EVENT_RESERVEDA = 0xe - EVENT_RESERVEDB = 0xf - VIDEORESIZE = 0x10 - VIDEOEXPOSE = 0x11 - EVENT_RESERVED2 = 0x12 - EVENT_RESERVED3 = 0x13 - EVENT_RESERVED4 = 0x14 - EVENT_RESERVED5 = 0x15 - EVENT_RESERVED6 = 0x16 - EVENT_RESERVED7 = 0x17 - USEREVENT = 0x18 - NUMEVENTS = 0x20 - ACTIVEEVENTMASK = 0x2 - KEYDOWNMASK = 0x4 - KEYUPMASK = 0x8 - KEYEVENTMASK = 0xc - MOUSEMOTIONMASK = 0x10 - MOUSEBUTTONDOWNMASK = 0x20 - MOUSEBUTTONUPMASK = 0x40 - MOUSEEVENTMASK = 0x70 - JOYAXISMOTIONMASK = 0x80 - JOYBALLMOTIONMASK = 0x100 - JOYHATMOTIONMASK = 0x200 - JOYBUTTONDOWNMASK = 0x400 - JOYBUTTONUPMASK = 0x800 - JOYEVENTMASK = 0xf80 - VIDEORESIZEMASK = 0x10000 - VIDEOEXPOSEMASK = 0x20000 - QUITMASK = 0x1000 - SYSWMEVENTMASK = 0x2000 - QUERY = -0x1 - DISABLE = 0 - ENABLE = 0x1 - K_UNKNOWN = 0 - K_FIRST = 0 - K_BACKSPACE = 0x8 - K_TAB = 0x9 - K_CLEAR = 0xc - K_RETURN = 0xd - K_PAUSE = 0x13 - K_ESCAPE = 0x1b - K_SPACE = 0x20 - K_EXCLAIM = 0x21 - K_QUOTEDBL = 0x22 - K_HASH = 0x23 - K_DOLLAR = 0x24 - K_AMPERSAND = 0x26 - K_QUOTE = 0x27 - K_LEFTPAREN = 0x28 - K_RIGHTPAREN = 0x29 - K_ASTERISK = 0x2a - K_PLUS = 0x2b - K_COMMA = 0x2c - K_MINUS = 0x2d - K_PERIOD = 0x2e - K_SLASH = 0x2f - K_0 = 0x30 - K_1 = 0x31 - K_2 = 0x32 - K_3 = 0x33 - K_4 = 0x34 - K_5 = 0x35 - K_6 = 0x36 - K_7 = 0x37 - K_8 = 0x38 - K_9 = 0x39 - K_COLON = 0x3a - K_SEMICOLON = 0x3b - K_LESS = 0x3c - K_EQUALS = 0x3d - K_GREATER = 0x3e - K_QUESTION = 0x3f - K_AT = 0x40 - K_LEFTBRACKET = 0x5b - K_BACKSLASH = 0x5c - K_RIGHTBRACKET = 0x5d - K_CARET = 0x5e - K_UNDERSCORE = 0x5f - K_BACKQUOTE = 0x60 - K_a = 0x61 - K_b = 0x62 - K_c = 0x63 - K_d = 0x64 - K_e = 0x65 - K_f = 0x66 - K_g = 0x67 - K_h = 0x68 - K_i = 0x69 - K_j = 0x6a - K_k = 0x6b - K_l = 0x6c - K_m = 0x6d - K_n = 0x6e - K_o = 0x6f - K_p = 0x70 - K_q = 0x71 - K_r = 0x72 - K_s = 0x73 - K_t = 0x74 - K_u = 0x75 - K_v = 0x76 - K_w = 0x77 - K_x = 0x78 - K_y = 0x79 - K_z = 0x7a - K_DELETE = 0x7f - K_WORLD_0 = 0xa0 - K_WORLD_1 = 0xa1 - K_WORLD_2 = 0xa2 - K_WORLD_3 = 0xa3 - K_WORLD_4 = 0xa4 - K_WORLD_5 = 0xa5 - K_WORLD_6 = 0xa6 - K_WORLD_7 = 0xa7 - K_WORLD_8 = 0xa8 - K_WORLD_9 = 0xa9 - K_WORLD_10 = 0xaa - K_WORLD_11 = 0xab - K_WORLD_12 = 0xac - K_WORLD_13 = 0xad - K_WORLD_14 = 0xae - K_WORLD_15 = 0xaf - K_WORLD_16 = 0xb0 - K_WORLD_17 = 0xb1 - K_WORLD_18 = 0xb2 - K_WORLD_19 = 0xb3 - K_WORLD_20 = 0xb4 - K_WORLD_21 = 0xb5 - K_WORLD_22 = 0xb6 - K_WORLD_23 = 0xb7 - K_WORLD_24 = 0xb8 - K_WORLD_25 = 0xb9 - K_WORLD_26 = 0xba - K_WORLD_27 = 0xbb - K_WORLD_28 = 0xbc - K_WORLD_29 = 0xbd - K_WORLD_30 = 0xbe - K_WORLD_31 = 0xbf - K_WORLD_32 = 0xc0 - K_WORLD_33 = 0xc1 - K_WORLD_34 = 0xc2 - K_WORLD_35 = 0xc3 - K_WORLD_36 = 0xc4 - K_WORLD_37 = 0xc5 - K_WORLD_38 = 0xc6 - K_WORLD_39 = 0xc7 - K_WORLD_40 = 0xc8 - K_WORLD_41 = 0xc9 - K_WORLD_42 = 0xca - K_WORLD_43 = 0xcb - K_WORLD_44 = 0xcc - K_WORLD_45 = 0xcd - K_WORLD_46 = 0xce - K_WORLD_47 = 0xcf - K_WORLD_48 = 0xd0 - K_WORLD_49 = 0xd1 - K_WORLD_50 = 0xd2 - K_WORLD_51 = 0xd3 - K_WORLD_52 = 0xd4 - K_WORLD_53 = 0xd5 - K_WORLD_54 = 0xd6 - K_WORLD_55 = 0xd7 - K_WORLD_56 = 0xd8 - K_WORLD_57 = 0xd9 - K_WORLD_58 = 0xda - K_WORLD_59 = 0xdb - K_WORLD_60 = 0xdc - K_WORLD_61 = 0xdd - K_WORLD_62 = 0xde - K_WORLD_63 = 0xdf - K_WORLD_64 = 0xe0 - K_WORLD_65 = 0xe1 - K_WORLD_66 = 0xe2 - K_WORLD_67 = 0xe3 - K_WORLD_68 = 0xe4 - K_WORLD_69 = 0xe5 - K_WORLD_70 = 0xe6 - K_WORLD_71 = 0xe7 - K_WORLD_72 = 0xe8 - K_WORLD_73 = 0xe9 - K_WORLD_74 = 0xea - K_WORLD_75 = 0xeb - K_WORLD_76 = 0xec - K_WORLD_77 = 0xed - K_WORLD_78 = 0xee - K_WORLD_79 = 0xef - K_WORLD_80 = 0xf0 - K_WORLD_81 = 0xf1 - K_WORLD_82 = 0xf2 - K_WORLD_83 = 0xf3 - K_WORLD_84 = 0xf4 - K_WORLD_85 = 0xf5 - K_WORLD_86 = 0xf6 - K_WORLD_87 = 0xf7 - K_WORLD_88 = 0xf8 - K_WORLD_89 = 0xf9 - K_WORLD_90 = 0xfa - K_WORLD_91 = 0xfb - K_WORLD_92 = 0xfc - K_WORLD_93 = 0xfd - K_WORLD_94 = 0xfe - K_WORLD_95 = 0xff - K_KP0 = 0x100 - K_KP1 = 0x101 - K_KP2 = 0x102 - K_KP3 = 0x103 - K_KP4 = 0x104 - K_KP5 = 0x105 - K_KP6 = 0x106 - K_KP7 = 0x107 - K_KP8 = 0x108 - K_KP9 = 0x109 - K_KP_PERIOD = 0x10a - K_KP_DIVIDE = 0x10b - K_KP_MULTIPLY = 0x10c - K_KP_MINUS = 0x10d - K_KP_PLUS = 0x10e - K_KP_ENTER = 0x10f - K_KP_EQUALS = 0x110 - K_UP = 0x111 - K_DOWN = 0x112 - K_RIGHT = 0x113 - K_LEFT = 0x114 - K_INSERT = 0x115 - K_HOME = 0x116 - K_END = 0x117 - K_PAGEUP = 0x118 - K_PAGEDOWN = 0x119 - K_F1 = 0x11a - K_F2 = 0x11b - K_F3 = 0x11c - K_F4 = 0x11d - K_F5 = 0x11e - K_F6 = 0x11f - K_F7 = 0x120 - K_F8 = 0x121 - K_F9 = 0x122 - K_F10 = 0x123 - K_F11 = 0x124 - K_F12 = 0x125 - K_F13 = 0x126 - K_F14 = 0x127 - K_F15 = 0x128 - K_NUMLOCK = 0x12c - K_CAPSLOCK = 0x12d - K_SCROLLOCK = 0x12e - K_RSHIFT = 0x12f - K_LSHIFT = 0x130 - K_RCTRL = 0x131 - K_LCTRL = 0x132 - K_RALT = 0x133 - K_LALT = 0x134 - K_RMETA = 0x135 - K_LMETA = 0x136 - K_LSUPER = 0x137 - K_RSUPER = 0x138 - K_MODE = 0x139 - K_COMPOSE = 0x13a - K_HELP = 0x13b - K_PRINT = 0x13c - K_SYSREQ = 0x13d - K_BREAK = 0x13e - K_MENU = 0x13f - K_POWER = 0x140 - K_EURO = 0x141 - K_UNDO = 0x142 - KMOD_NONE = 0 - KMOD_LSHIFT = 0x1 - KMOD_RSHIFT = 0x2 - KMOD_LCTRL = 0x40 - KMOD_RCTRL = 0x80 - KMOD_LALT = 0x100 - KMOD_RALT = 0x200 - KMOD_LMETA = 0x400 - KMOD_RMETA = 0x800 - KMOD_NUM = 0x1000 - KMOD_CAPS = 0x2000 - KMOD_MODE = 0x4000 - KMOD_RESERVED = 0x8000 - HAT_CENTERED = 0 - HAT_UP = 0x1 - HAT_RIGHT = 0x2 - HAT_DOWN = 0x4 - HAT_LEFT = 0x8 - HAT_RIGHTUP = 0x3 - HAT_RIGHTDOWN = 0x6 - HAT_LEFTUP = 0x9 - HAT_LEFTDOWN = 0xc + INIT_AUDIO = 0x10 + INIT_VIDEO = 0x20 + INIT_CDROM = 0x100 + INIT_TIMER = 0x1 + INIT_JOYSTICK = 0x200 + INIT_NOPARACHUTE = 0x100000 + INIT_EVENTTHREAD = 0x1000000 + INIT_EVERYTHING = 0xffff + SWSURFACE = 0 + HWSURFACE = 0x1 + ASYNCBLIT = 0x4 + ANYFORMAT = 0x10000000 + HWPALETTE = 0x20000000 + DOUBLEBUF = 0x40000000 + FULLSCREEN = 0x80000000 + OPENGL = 0x2 + OPENGLBLIT = 0xa + RESIZABLE = 0x10 + NOFRAME = 0x20 + HWACCEL = 0x100 + SRCCOLORKEY = 0x1000 + RLEACCELOK = 0x2000 + RLEACCEL = 0x4000 + SRCALPHA = 0x10000 + PREALLOC = 0x1000000 + YV12_OVERLAY = 0x32315659 + IYUV_OVERLAY = 0x56555949 + YUY2_OVERLAY = 0x32595559 + UYVY_OVERLAY = 0x59565955 + YVYU_OVERLAY = 0x55595659 + LOGPAL = 0x1 + PHYSPAL = 0x2 + GL_RED_SIZE = 0 + GL_GREEN_SIZE = 0x1 + GL_BLUE_SIZE = 0x2 + GL_ALPHA_SIZE = 0x3 + GL_BUFFER_SIZE = 0x4 + GL_DOUBLEBUFFER = 0x5 + GL_DEPTH_SIZE = 0x6 + GL_STENCIL_SIZE = 0x7 + GL_ACCUM_RED_SIZE = 0x8 + GL_ACCUM_GREEN_SIZE = 0x9 + GL_ACCUM_BLUE_SIZE = 0xa + GL_ACCUM_ALPHA_SIZE = 0xb + GL_STEREO = 0xc + GL_MULTISAMPLEBUFFERS = 0xd + GL_MULTISAMPLESAMPLES = 0xe + GL_ACCELERATED_VISUAL = 0xf + GL_SWAP_CONTROL = 0x10 + NOEVENT = 0 + ACTIVEEVENT = 0x1 + KEYDOWN = 0x2 + KEYUP = 0x3 + MOUSEMOTION = 0x4 + MOUSEBUTTONDOWN = 0x5 + MOUSEBUTTONUP = 0x6 + JOYAXISMOTION = 0x7 + JOYBALLMOTION = 0x8 + JOYHATMOTION = 0x9 + JOYBUTTONDOWN = 0xa + JOYBUTTONUP = 0xb + QUIT = 0xc + SYSWMEVENT = 0xd + EVENT_RESERVEDA = 0xe + EVENT_RESERVEDB = 0xf + VIDEORESIZE = 0x10 + VIDEOEXPOSE = 0x11 + EVENT_RESERVED2 = 0x12 + EVENT_RESERVED3 = 0x13 + EVENT_RESERVED4 = 0x14 + EVENT_RESERVED5 = 0x15 + EVENT_RESERVED6 = 0x16 + EVENT_RESERVED7 = 0x17 + USEREVENT = 0x18 + NUMEVENTS = 0x20 + ACTIVEEVENTMASK = 0x2 + KEYDOWNMASK = 0x4 + KEYUPMASK = 0x8 + KEYEVENTMASK = 0xc + MOUSEMOTIONMASK = 0x10 + MOUSEBUTTONDOWNMASK = 0x20 + MOUSEBUTTONUPMASK = 0x40 + MOUSEEVENTMASK = 0x70 + JOYAXISMOTIONMASK = 0x80 + JOYBALLMOTIONMASK = 0x100 + JOYHATMOTIONMASK = 0x200 + JOYBUTTONDOWNMASK = 0x400 + JOYBUTTONUPMASK = 0x800 + JOYEVENTMASK = 0xf80 + VIDEORESIZEMASK = 0x10000 + VIDEOEXPOSEMASK = 0x20000 + QUITMASK = 0x1000 + SYSWMEVENTMASK = 0x2000 + QUERY = -0x1 + DISABLE = 0 + ENABLE = 0x1 + K_UNKNOWN = 0 + K_FIRST = 0 + K_BACKSPACE = 0x8 + K_TAB = 0x9 + K_CLEAR = 0xc + K_RETURN = 0xd + K_PAUSE = 0x13 + K_ESCAPE = 0x1b + K_SPACE = 0x20 + K_EXCLAIM = 0x21 + K_QUOTEDBL = 0x22 + K_HASH = 0x23 + K_DOLLAR = 0x24 + K_AMPERSAND = 0x26 + K_QUOTE = 0x27 + K_LEFTPAREN = 0x28 + K_RIGHTPAREN = 0x29 + K_ASTERISK = 0x2a + K_PLUS = 0x2b + K_COMMA = 0x2c + K_MINUS = 0x2d + K_PERIOD = 0x2e + K_SLASH = 0x2f + K_0 = 0x30 + K_1 = 0x31 + K_2 = 0x32 + K_3 = 0x33 + K_4 = 0x34 + K_5 = 0x35 + K_6 = 0x36 + K_7 = 0x37 + K_8 = 0x38 + K_9 = 0x39 + K_COLON = 0x3a + K_SEMICOLON = 0x3b + K_LESS = 0x3c + K_EQUALS = 0x3d + K_GREATER = 0x3e + K_QUESTION = 0x3f + K_AT = 0x40 + K_LEFTBRACKET = 0x5b + K_BACKSLASH = 0x5c + K_RIGHTBRACKET = 0x5d + K_CARET = 0x5e + K_UNDERSCORE = 0x5f + K_BACKQUOTE = 0x60 + K_a = 0x61 + K_b = 0x62 + K_c = 0x63 + K_d = 0x64 + K_e = 0x65 + K_f = 0x66 + K_g = 0x67 + K_h = 0x68 + K_i = 0x69 + K_j = 0x6a + K_k = 0x6b + K_l = 0x6c + K_m = 0x6d + K_n = 0x6e + K_o = 0x6f + K_p = 0x70 + K_q = 0x71 + K_r = 0x72 + K_s = 0x73 + K_t = 0x74 + K_u = 0x75 + K_v = 0x76 + K_w = 0x77 + K_x = 0x78 + K_y = 0x79 + K_z = 0x7a + K_DELETE = 0x7f + K_WORLD_0 = 0xa0 + K_WORLD_1 = 0xa1 + K_WORLD_2 = 0xa2 + K_WORLD_3 = 0xa3 + K_WORLD_4 = 0xa4 + K_WORLD_5 = 0xa5 + K_WORLD_6 = 0xa6 + K_WORLD_7 = 0xa7 + K_WORLD_8 = 0xa8 + K_WORLD_9 = 0xa9 + K_WORLD_10 = 0xaa + K_WORLD_11 = 0xab + K_WORLD_12 = 0xac + K_WORLD_13 = 0xad + K_WORLD_14 = 0xae + K_WORLD_15 = 0xaf + K_WORLD_16 = 0xb0 + K_WORLD_17 = 0xb1 + K_WORLD_18 = 0xb2 + K_WORLD_19 = 0xb3 + K_WORLD_20 = 0xb4 + K_WORLD_21 = 0xb5 + K_WORLD_22 = 0xb6 + K_WORLD_23 = 0xb7 + K_WORLD_24 = 0xb8 + K_WORLD_25 = 0xb9 + K_WORLD_26 = 0xba + K_WORLD_27 = 0xbb + K_WORLD_28 = 0xbc + K_WORLD_29 = 0xbd + K_WORLD_30 = 0xbe + K_WORLD_31 = 0xbf + K_WORLD_32 = 0xc0 + K_WORLD_33 = 0xc1 + K_WORLD_34 = 0xc2 + K_WORLD_35 = 0xc3 + K_WORLD_36 = 0xc4 + K_WORLD_37 = 0xc5 + K_WORLD_38 = 0xc6 + K_WORLD_39 = 0xc7 + K_WORLD_40 = 0xc8 + K_WORLD_41 = 0xc9 + K_WORLD_42 = 0xca + K_WORLD_43 = 0xcb + K_WORLD_44 = 0xcc + K_WORLD_45 = 0xcd + K_WORLD_46 = 0xce + K_WORLD_47 = 0xcf + K_WORLD_48 = 0xd0 + K_WORLD_49 = 0xd1 + K_WORLD_50 = 0xd2 + K_WORLD_51 = 0xd3 + K_WORLD_52 = 0xd4 + K_WORLD_53 = 0xd5 + K_WORLD_54 = 0xd6 + K_WORLD_55 = 0xd7 + K_WORLD_56 = 0xd8 + K_WORLD_57 = 0xd9 + K_WORLD_58 = 0xda + K_WORLD_59 = 0xdb + K_WORLD_60 = 0xdc + K_WORLD_61 = 0xdd + K_WORLD_62 = 0xde + K_WORLD_63 = 0xdf + K_WORLD_64 = 0xe0 + K_WORLD_65 = 0xe1 + K_WORLD_66 = 0xe2 + K_WORLD_67 = 0xe3 + K_WORLD_68 = 0xe4 + K_WORLD_69 = 0xe5 + K_WORLD_70 = 0xe6 + K_WORLD_71 = 0xe7 + K_WORLD_72 = 0xe8 + K_WORLD_73 = 0xe9 + K_WORLD_74 = 0xea + K_WORLD_75 = 0xeb + K_WORLD_76 = 0xec + K_WORLD_77 = 0xed + K_WORLD_78 = 0xee + K_WORLD_79 = 0xef + K_WORLD_80 = 0xf0 + K_WORLD_81 = 0xf1 + K_WORLD_82 = 0xf2 + K_WORLD_83 = 0xf3 + K_WORLD_84 = 0xf4 + K_WORLD_85 = 0xf5 + K_WORLD_86 = 0xf6 + K_WORLD_87 = 0xf7 + K_WORLD_88 = 0xf8 + K_WORLD_89 = 0xf9 + K_WORLD_90 = 0xfa + K_WORLD_91 = 0xfb + K_WORLD_92 = 0xfc + K_WORLD_93 = 0xfd + K_WORLD_94 = 0xfe + K_WORLD_95 = 0xff + K_KP0 = 0x100 + K_KP1 = 0x101 + K_KP2 = 0x102 + K_KP3 = 0x103 + K_KP4 = 0x104 + K_KP5 = 0x105 + K_KP6 = 0x106 + K_KP7 = 0x107 + K_KP8 = 0x108 + K_KP9 = 0x109 + K_KP_PERIOD = 0x10a + K_KP_DIVIDE = 0x10b + K_KP_MULTIPLY = 0x10c + K_KP_MINUS = 0x10d + K_KP_PLUS = 0x10e + K_KP_ENTER = 0x10f + K_KP_EQUALS = 0x110 + K_UP = 0x111 + K_DOWN = 0x112 + K_RIGHT = 0x113 + K_LEFT = 0x114 + K_INSERT = 0x115 + K_HOME = 0x116 + K_END = 0x117 + K_PAGEUP = 0x118 + K_PAGEDOWN = 0x119 + K_F1 = 0x11a + K_F2 = 0x11b + K_F3 = 0x11c + K_F4 = 0x11d + K_F5 = 0x11e + K_F6 = 0x11f + K_F7 = 0x120 + K_F8 = 0x121 + K_F9 = 0x122 + K_F10 = 0x123 + K_F11 = 0x124 + K_F12 = 0x125 + K_F13 = 0x126 + K_F14 = 0x127 + K_F15 = 0x128 + K_NUMLOCK = 0x12c + K_CAPSLOCK = 0x12d + K_SCROLLOCK = 0x12e + K_RSHIFT = 0x12f + K_LSHIFT = 0x130 + K_RCTRL = 0x131 + K_LCTRL = 0x132 + K_RALT = 0x133 + K_LALT = 0x134 + K_RMETA = 0x135 + K_LMETA = 0x136 + K_LSUPER = 0x137 + K_RSUPER = 0x138 + K_MODE = 0x139 + K_COMPOSE = 0x13a + K_HELP = 0x13b + K_PRINT = 0x13c + K_SYSREQ = 0x13d + K_BREAK = 0x13e + K_MENU = 0x13f + K_POWER = 0x140 + K_EURO = 0x141 + K_UNDO = 0x142 + KMOD_NONE = 0 + KMOD_LSHIFT = 0x1 + KMOD_RSHIFT = 0x2 + KMOD_LCTRL = 0x40 + KMOD_RCTRL = 0x80 + KMOD_LALT = 0x100 + KMOD_RALT = 0x200 + KMOD_LMETA = 0x400 + KMOD_RMETA = 0x800 + KMOD_NUM = 0x1000 + KMOD_CAPS = 0x2000 + KMOD_MODE = 0x4000 + KMOD_RESERVED = 0x8000 + HAT_CENTERED = 0 + HAT_UP = 0x1 + HAT_RIGHT = 0x2 + HAT_DOWN = 0x4 + HAT_LEFT = 0x8 + HAT_RIGHTUP = 0x3 + HAT_RIGHTDOWN = 0x6 + HAT_LEFTUP = 0x9 + HAT_LEFTDOWN = 0xc ) // Types From 392a2f14855da0d1e38e368bd0ba7e425d8f4490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 12 Dec 2011 13:10:40 +0100 Subject: [PATCH 38/79] Remove the "4s" directory --- 4s/4s.go | 42 ------------------------------------------ 4s/Makefile | 16 ---------------- 4s/xs.patch | 15 --------------- Makefile | 1 - 4 files changed, 74 deletions(-) delete mode 100644 4s/4s.go delete mode 100644 4s/Makefile delete mode 100644 4s/xs.patch diff --git a/4s/4s.go b/4s/4s.go deleted file mode 100644 index 03a8af6..0000000 --- a/4s/4s.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// this is SDL version of src/pkg/exp/4s/4s.go -// if you want to run int enable exp/draw support in sdl/Makefile - -package main - -import ( - "atom/sdl" - "log" - "os" - "runtime" -) - - -func main() { - - runtime.LockOSThread() - - args := os.Args - p := pieces4 - if len(args) > 1 && args[1] == "-5" { - p = pieces5 - } - dx, dy := 500, 500 - w, err := sdl.InitContext(dx, dy) - if err != nil { - log.Exit(err) - } - - Play(p, w) -} - -func PlaySound(b []uint16) { - // no audio yet -} - -var whoosh = []uint16{ -// Insert your favorite sound samples here. -} diff --git a/4s/Makefile b/4s/Makefile deleted file mode 100644 index 4d95ad1..0000000 --- a/4s/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -all: 8.out - -KSDIR:=$(GOROOT)/src/pkg/exp/4s/ - -4s.8: 4s.go $(KSDIR)/data.go $(KSDIR)//xs.go - 8g 4s.go $(KSDIR)/data.go $(KSDIR)/xs.go - -8.out: 4s.8 - 8l 4s.8 - -clean: - rm -f *.8 8.out diff --git a/4s/xs.patch b/4s/xs.patch deleted file mode 100644 index 3094e4d..0000000 --- a/4s/xs.patch +++ /dev/null @@ -1,15 +0,0 @@ -# apply this patch if you are geting this error: -# /src/pkg/exp/4s//xs.go:729: cannot use int32((time.Nanoseconds()) % 999999999) (type int32) as type int64 in function argument -# -diff -r 2f32e74ab96e src/pkg/exp/4s/xs.go ---- a/src/pkg/exp/4s/xs.go Sat Nov 21 15:53:03 2009 -0800 -+++ b/src/pkg/exp/4s/xs.go Mon Nov 23 17:39:28 2009 +0100 -@@ -726,7 +726,7 @@ - pieces = pp; - N = len(pieces[0].d); - initPieces(); -- rand.Seed(int32(time.Nanoseconds() % (1e9 - 1))); -+ rand.Seed(int64(time.Nanoseconds() % (1e9 - 1))); - whitemask = draw.White.SetAlpha(0x7F); - tsleep = 50; - timerc = time.Tick(int64(tsleep/2) * 1e6); diff --git a/Makefile b/Makefile index a4a3328..4a3e8ee 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,6 @@ clean: gomake -C sdl/audio clean gomake -C ttf clean gomake -C mixer clean - gomake -C 4s clean gomake -C test clean gomake -C gfx clean gomake -C doc clean From 9b7741f349effb3533696e78c03fff61ce5bb6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 20 Feb 2012 20:24:04 +0100 Subject: [PATCH 39/79] Update to meet the requirements of Go1 --- .gitignore | 14 +- Makefile | 31 -- README.md | 11 +- TODO | 4 - doc/Makefile | 6 - gfx/Makefile | 14 - gfx/framerate.go | 8 +- mixer/Makefile | 14 - mixer/constants.go | 2 +- mixer/mixer.go | 1 - {doc => sdl-template}/template.go | 6 +- {test => sdl-test}/Fontin Sans.otf | Bin {test => sdl-test}/test.go | 26 +- {test => sdl-test}/test.ogg | Bin {test => sdl-test}/test.png | Bin sdl/Makefile | 12 - sdl/audio/Makefile | 17 - sdl/audio/audio.go | 4 + sdl/constants.c | 385 ------------- sdl/constants.go | 740 +++++++++++++------------ sdl/{structs.8.go => structs_386.go} | 0 sdl/{structs.6.go => structs_amd64.go} | 0 test/Makefile | 10 - ttf/Makefile | 15 - ttf/constants.go | 1 - ttf/ttf.go | 9 +- 26 files changed, 428 insertions(+), 902 deletions(-) delete mode 100644 Makefile delete mode 100644 TODO delete mode 100644 doc/Makefile delete mode 100644 gfx/Makefile delete mode 100644 mixer/Makefile rename {doc => sdl-template}/template.go (90%) rename {test => sdl-test}/Fontin Sans.otf (100%) rename {test => sdl-test}/test.go (88%) rename {test => sdl-test}/test.ogg (100%) rename {test => sdl-test}/test.png (100%) delete mode 100644 sdl/Makefile delete mode 100644 sdl/audio/Makefile delete mode 100644 sdl/constants.c rename sdl/{structs.8.go => structs_386.go} (100%) rename sdl/{structs.6.go => structs_amd64.go} (100%) delete mode 100644 test/Makefile delete mode 100644 ttf/Makefile diff --git a/.gitignore b/.gitignore index 2960171..7cd9e90 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,2 @@ -*~ -*.[o68] -_obj -*.cgo*.go -*.cgo*.c -*.cgo*.[68] -*cgo*.so -*.out -test/test -shoot.png -*_cgo* -sdl_audio_callback.so +sdl-test/sdl-test +sdl-template/sdl-template diff --git a/Makefile b/Makefile deleted file mode 100644 index 4a3e8ee..0000000 --- a/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -all: install - -install: - gomake clean - gomake -C sdl install - gomake -C sdl/audio install - gomake -C ttf install - gomake -C mixer install - gomake -C gfx install - -clean: - gomake -C sdl clean - gomake -C sdl/audio clean - gomake -C ttf clean - gomake -C mixer clean - gomake -C test clean - gomake -C gfx clean - gomake -C doc clean - -nuke: - gomake -C sdl nuke - gomake -C sdl/audio nuke - gomake -C ttf nuke - gomake -C mixer nuke - gomake -C gfx nuke diff --git a/README.md b/README.md index 9738d52..741a104 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,22 @@ This is an improved version of Banthar's [Go-SDL](http://github.com/banthar/Go-S The improvements/differences are: -* SDL functions (except for SDL-mixer) can be safely called from multiple concurrent goroutines +* SDL functions (except for SDL-mixer) can be safely called from concurrently + running goroutines * All SDL events are delivered via a Go channel * Support for low-level SDL sound functions * Can be installed in parallel to Banthar's Go-SDL -* The import path is "atom/sdl", instead of "sdl" +* The import paths are "github.com/0xe2-0x9a-0x9b/Go-SDL/..." # Installation -Make sure you have SDL, SDL-image, SDL-mixer, and SDL-ttf (all in -dev version). +Make sure you have SDL, SDL-image, SDL-mixer and SDL-ttf (all in -dev version). -To install, run 'make' in the top-level directory. If it fails to compile, try to run 'hg pull; hg update release' in $GOROOT and rebuild Go. +Installing libraries and examples: + + go get -v github.com/0xe2-0x9a-0x9b/Go-SDL/... # Credits diff --git a/TODO b/TODO deleted file mode 100644 index 1c1b9ce..0000000 --- a/TODO +++ /dev/null @@ -1,4 +0,0 @@ -* missing functions, threads and file access are useless in Go, but there are probably some usefull functions left -* add joystick support -* other SDL libraries: SGE, gfx ... -* more/better test/example apps diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 7d84aaf..0000000 --- a/doc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -include $(GOROOT)/src/Make.inc - -TARG=template -GOFILES=template.go - -include $(GOROOT)/src/Make.cmd diff --git a/gfx/Makefile b/gfx/Makefile deleted file mode 100644 index 4fafc8c..0000000 --- a/gfx/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=atom/sdl/gfx - -GOFILES:=constants.go\ - framerate.go - -CLEANFILES+=gfx - -include $(GOROOT)/src/Make.pkg diff --git a/gfx/framerate.go b/gfx/framerate.go index 028e931..bc3cd03 100644 --- a/gfx/framerate.go +++ b/gfx/framerate.go @@ -20,7 +20,7 @@ func NewFramerate() *FPSmanager { framecount: 0, rate: FPS_DEFAULT, rateticks: (1000.0 / float64(FPS_DEFAULT)), - lastticks: uint64(time.Nanoseconds()) / 1e6, + lastticks: uint64(time.Now().UnixNano()) / 1e6, } } @@ -44,14 +44,14 @@ func (manager *FPSmanager) FramerateDelay() { manager.framecount++ // get/calc ticks - current_ticks = uint64(time.Nanoseconds()) / 1e6 + current_ticks = uint64(time.Now().UnixNano()) / 1e6 target_ticks = manager.lastticks + uint64(float64(manager.framecount)*manager.rateticks) if current_ticks <= target_ticks { the_delay = target_ticks - current_ticks - time.Sleep(int64(the_delay) * 1e6) + time.Sleep(time.Duration(the_delay * 1e6)) } else { manager.framecount = 0 - manager.lastticks = uint64(time.Nanoseconds()) / 1e6 + manager.lastticks = uint64(time.Now().UnixNano()) / 1e6 } } diff --git a/mixer/Makefile b/mixer/Makefile deleted file mode 100644 index 2623857..0000000 --- a/mixer/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=atom/sdl/mixer - -GOFILES:=constants.go -CGOFILES:=mixer.go - -CLEANFILES+=mixer - -include $(GOROOT)/src/Make.pkg diff --git a/mixer/constants.go b/mixer/constants.go index de7fc68..ee26227 100644 --- a/mixer/constants.go +++ b/mixer/constants.go @@ -1,6 +1,6 @@ package mixer -//TODO: Autogenerate these values and add rest of constants +//TODO: Add rest of constants from SDL include files const ( AUDIO_U8 = 0x0008 AUDIO_S8 = 0x8008 diff --git a/mixer/mixer.go b/mixer/mixer.go index 4f3728e..0ae3ebc 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -86,7 +86,6 @@ func HaltMusic() { C.Mix_HaltMusic() } // the fade out is completed. func FadeOutMusic(ms int) int { return int(C.Mix_FadeOutMusic(C.int(ms))) } - // Returns the type of the currently playing music. func GetMusicType() int { return int(C.Mix_GetMusicType(nil)) } diff --git a/doc/template.go b/sdl-template/template.go similarity index 90% rename from doc/template.go rename to sdl-template/template.go index ef6ac1c..2ad1fd8 100644 --- a/doc/template.go +++ b/sdl-template/template.go @@ -1,9 +1,9 @@ package main import ( - "atom/sdl" "fmt" - "rand" + "github.com/0xe2-0x9a-0x9b/Go-SDL/sdl" + "math/rand" "time" ) @@ -46,7 +46,7 @@ loop: case event := <-sdl.Events: fmt.Printf("%#v\n", event) - switch e := event.(type) { + switch event.(type) { case sdl.QuitEvent: break loop } diff --git a/test/Fontin Sans.otf b/sdl-test/Fontin Sans.otf similarity index 100% rename from test/Fontin Sans.otf rename to sdl-test/Fontin Sans.otf diff --git a/test/test.go b/sdl-test/test.go similarity index 88% rename from test/test.go rename to sdl-test/test.go index 0a04c74..6fa9291 100644 --- a/test/test.go +++ b/sdl-test/test.go @@ -1,11 +1,13 @@ package main import ( - "atom/sdl" - "atom/sdl/ttf" - "atom/sdl/mixer" - "math" "fmt" + "github.com/0xe2-0x9a-0x9b/Go-SDL/mixer" + "github.com/0xe2-0x9a-0x9b/Go-SDL/sdl" + "github.com/0xe2-0x9a-0x9b/Go-SDL/ttf" + "math" + "os" + "strings" "time" ) @@ -41,6 +43,16 @@ func worm(in <-chan Point, out chan<- Point, draw chan<- Point) { } func main() { + var resourcePath string + { + gopaths := os.Getenv("GOPATH") + if gopaths == "" { + panic("No such environment variable: GOPATH") + } + gopath := strings.Split(gopaths, ":")[0] + resourcePath = gopath + "/src/github.com/0xe2-0x9a-0x9b/Go-SDL/sdl-test" + } + var joy *sdl.Joystick if sdl.Init(sdl.INIT_EVERYTHING) != 0 { panic(sdl.GetError()) @@ -86,7 +98,7 @@ func main() { sdl.WM_SetCaption("Go-SDL SDL Test", "") - image := sdl.Load("test.png") + image := sdl.Load(resourcePath + "/test.png") if image == nil { panic(sdl.GetError()) @@ -96,7 +108,7 @@ func main() { running := true - font := ttf.OpenFont("Fontin Sans.otf", 72) + font := ttf.OpenFont(resourcePath+"/Fontin Sans.otf", 72) if font == nil { panic(sdl.GetError()) @@ -105,7 +117,7 @@ func main() { font.SetStyle(ttf.STYLE_UNDERLINE) white := sdl.Color{255, 255, 255, 0} text := ttf.RenderText_Blended(font, "Test (with music)", white) - music := mixer.LoadMUS("test.ogg") + music := mixer.LoadMUS(resourcePath + "/test.ogg") if music == nil { panic(sdl.GetError()) diff --git a/test/test.ogg b/sdl-test/test.ogg similarity index 100% rename from test/test.ogg rename to sdl-test/test.ogg diff --git a/test/test.png b/sdl-test/test.png similarity index 100% rename from test/test.png rename to sdl-test/test.png diff --git a/sdl/Makefile b/sdl/Makefile deleted file mode 100644 index 3ae6b64..0000000 --- a/sdl/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include $(GOROOT)/src/Make.inc - -TARG=atom/sdl - -GOFILES:=constants.go event.go structs.$(O).go -CGOFILES:=sdl.go - -include $(GOROOT)/src/Make.pkg - -constants.go: constants.c - godefs -g sdl constants.c > constants.go - gofmt -w constants.go diff --git a/sdl/audio/Makefile b/sdl/audio/Makefile deleted file mode 100644 index 512ef33..0000000 --- a/sdl/audio/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -include $(GOROOT)/src/Make.inc - -TARG=atom/sdl/audio - -CGOFILES=audio.go -CGO_OFILES=callback.o - -ifeq ($(GOOS),windows) -CGO_LDFLAGS=-lpthread -else -CGO_LDFLAGS=-lrt -endif - -include $(GOROOT)/src/Make.pkg - -_cgo_defun.c: callback.h -callback.o: callback.h diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index a6dbcb1..058d2b3 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -8,6 +8,10 @@ package audio // #cgo pkg-config: sdl +// #cgo darwin LDFLAGS: -lrt +// #cgo freebsd LDFLAGS: -lrt +// #cgo linux LDFLAGS: -lrt +// #cgo windows LDFLAGS: -lpthread // #include // #include "callback.h" import "C" diff --git a/sdl/constants.c b/sdl/constants.c deleted file mode 100644 index 307f8ff..0000000 --- a/sdl/constants.c +++ /dev/null @@ -1,385 +0,0 @@ -#include - -enum -{ - -// init flags - - $INIT_AUDIO = SDL_INIT_AUDIO, - $INIT_VIDEO = SDL_INIT_VIDEO, - $INIT_CDROM = SDL_INIT_CDROM, - $INIT_TIMER = SDL_INIT_TIMER, - $INIT_JOYSTICK = SDL_INIT_JOYSTICK, - $INIT_NOPARACHUTE = SDL_INIT_NOPARACHUTE, - $INIT_EVENTTHREAD = SDL_INIT_EVENTTHREAD, - $INIT_EVERYTHING = SDL_INIT_EVERYTHING, - -// setvideo flags - - $SWSURFACE = SDL_SWSURFACE, - $HWSURFACE = SDL_HWSURFACE, - $ASYNCBLIT = SDL_ASYNCBLIT, - $ANYFORMAT = SDL_ANYFORMAT, - $HWPALETTE = SDL_HWPALETTE, - $DOUBLEBUF = SDL_DOUBLEBUF, - $FULLSCREEN = SDL_FULLSCREEN, - $OPENGL = SDL_OPENGL, - $OPENGLBLIT = SDL_OPENGLBLIT, - $RESIZABLE = SDL_RESIZABLE, - $NOFRAME = SDL_NOFRAME, - $HWACCEL = SDL_HWACCEL, - $SRCCOLORKEY = SDL_SRCCOLORKEY, - $RLEACCELOK = SDL_RLEACCELOK, - $RLEACCEL = SDL_RLEACCEL, - $SRCALPHA = SDL_SRCALPHA, - $PREALLOC = SDL_PREALLOC, - $YV12_OVERLAY = SDL_YV12_OVERLAY, - $IYUV_OVERLAY = SDL_IYUV_OVERLAY, - $YUY2_OVERLAY = SDL_YUY2_OVERLAY, - $UYVY_OVERLAY = SDL_UYVY_OVERLAY, - $YVYU_OVERLAY = SDL_YVYU_OVERLAY, - $LOGPAL = SDL_LOGPAL, - $PHYSPAL = SDL_PHYSPAL, - -// More setvideo flags: GLattr enumeration - - $GL_RED_SIZE = SDL_GL_RED_SIZE, - $GL_GREEN_SIZE = SDL_GL_GREEN_SIZE, - $GL_BLUE_SIZE = SDL_GL_BLUE_SIZE, - $GL_ALPHA_SIZE = SDL_GL_ALPHA_SIZE, - $GL_BUFFER_SIZE = SDL_GL_BUFFER_SIZE, - $GL_DOUBLEBUFFER = SDL_GL_DOUBLEBUFFER, - $GL_DEPTH_SIZE = SDL_GL_DEPTH_SIZE, - $GL_STENCIL_SIZE = SDL_GL_STENCIL_SIZE, - $GL_ACCUM_RED_SIZE = SDL_GL_ACCUM_RED_SIZE, - $GL_ACCUM_GREEN_SIZE = SDL_GL_ACCUM_GREEN_SIZE, - $GL_ACCUM_BLUE_SIZE = SDL_GL_ACCUM_BLUE_SIZE, - $GL_ACCUM_ALPHA_SIZE = SDL_GL_ACCUM_ALPHA_SIZE, - $GL_STEREO = SDL_GL_STEREO, - $GL_MULTISAMPLEBUFFERS = SDL_GL_MULTISAMPLEBUFFERS, - $GL_MULTISAMPLESAMPLES = SDL_GL_MULTISAMPLESAMPLES, - $GL_ACCELERATED_VISUAL = SDL_GL_ACCELERATED_VISUAL, - $GL_SWAP_CONTROL = SDL_GL_SWAP_CONTROL, - -// event types - - $NOEVENT = SDL_NOEVENT, - $ACTIVEEVENT = SDL_ACTIVEEVENT, - $KEYDOWN = SDL_KEYDOWN, - $KEYUP = SDL_KEYUP, - $MOUSEMOTION = SDL_MOUSEMOTION, - $MOUSEBUTTONDOWN = SDL_MOUSEBUTTONDOWN, - $MOUSEBUTTONUP = SDL_MOUSEBUTTONUP, - $JOYAXISMOTION = SDL_JOYAXISMOTION, - $JOYBALLMOTION = SDL_JOYBALLMOTION, - $JOYHATMOTION = SDL_JOYHATMOTION, - $JOYBUTTONDOWN = SDL_JOYBUTTONDOWN, - $JOYBUTTONUP = SDL_JOYBUTTONUP, - $QUIT = SDL_QUIT, - $SYSWMEVENT = SDL_SYSWMEVENT, - $EVENT_RESERVEDA = SDL_EVENT_RESERVEDA, - $EVENT_RESERVEDB = SDL_EVENT_RESERVEDB, - $VIDEORESIZE = SDL_VIDEORESIZE, - $VIDEOEXPOSE = SDL_VIDEOEXPOSE, - $EVENT_RESERVED2 = SDL_EVENT_RESERVED2, - $EVENT_RESERVED3 = SDL_EVENT_RESERVED3, - $EVENT_RESERVED4 = SDL_EVENT_RESERVED4, - $EVENT_RESERVED5 = SDL_EVENT_RESERVED5, - $EVENT_RESERVED6 = SDL_EVENT_RESERVED6, - $EVENT_RESERVED7 = SDL_EVENT_RESERVED7, - - $USEREVENT = SDL_USEREVENT, - - $NUMEVENTS = SDL_NUMEVENTS, - -// event masks - - $ACTIVEEVENTMASK = SDL_ACTIVEEVENTMASK, - $KEYDOWNMASK = SDL_KEYDOWNMASK, - $KEYUPMASK = SDL_KEYUPMASK, - $KEYEVENTMASK = SDL_KEYEVENTMASK, - $MOUSEMOTIONMASK = SDL_MOUSEMOTIONMASK, - $MOUSEBUTTONDOWNMASK = SDL_MOUSEBUTTONDOWNMASK, - $MOUSEBUTTONUPMASK = SDL_MOUSEBUTTONUPMASK, - $MOUSEEVENTMASK = SDL_MOUSEEVENTMASK, - $JOYAXISMOTIONMASK = SDL_JOYAXISMOTIONMASK, - $JOYBALLMOTIONMASK = SDL_JOYBALLMOTIONMASK, - $JOYHATMOTIONMASK = SDL_JOYHATMOTIONMASK, - $JOYBUTTONDOWNMASK = SDL_JOYBUTTONDOWNMASK, - $JOYBUTTONUPMASK = SDL_JOYBUTTONUPMASK, - $JOYEVENTMASK = SDL_JOYEVENTMASK, - $VIDEORESIZEMASK = SDL_VIDEORESIZEMASK, - $VIDEOEXPOSEMASK = SDL_VIDEOEXPOSEMASK, - $QUITMASK = SDL_QUITMASK, - $SYSWMEVENTMASK = SDL_SYSWMEVENTMASK, - -// event state - - $QUERY = SDL_QUERY, - $DISABLE = SDL_DISABLE, - $ENABLE = SDL_ENABLE, - -// keys - $K_UNKNOWN = SDLK_UNKNOWN, - $K_FIRST = SDLK_FIRST, - $K_BACKSPACE = SDLK_BACKSPACE, - $K_TAB = SDLK_TAB, - $K_CLEAR = SDLK_CLEAR, - $K_RETURN = SDLK_RETURN, - $K_PAUSE = SDLK_PAUSE, - $K_ESCAPE = SDLK_ESCAPE, - $K_SPACE = SDLK_SPACE, - $K_EXCLAIM = SDLK_EXCLAIM, - $K_QUOTEDBL = SDLK_QUOTEDBL, - $K_HASH = SDLK_HASH, - $K_DOLLAR = SDLK_DOLLAR, - $K_AMPERSAND = SDLK_AMPERSAND, - $K_QUOTE = SDLK_QUOTE, - $K_LEFTPAREN = SDLK_LEFTPAREN, - $K_RIGHTPAREN = SDLK_RIGHTPAREN, - $K_ASTERISK = SDLK_ASTERISK, - $K_PLUS = SDLK_PLUS, - $K_COMMA = SDLK_COMMA, - $K_MINUS = SDLK_MINUS, - $K_PERIOD = SDLK_PERIOD, - $K_SLASH = SDLK_SLASH, - $K_0 = SDLK_0, - $K_1 = SDLK_1, - $K_2 = SDLK_2, - $K_3 = SDLK_3, - $K_4 = SDLK_4, - $K_5 = SDLK_5, - $K_6 = SDLK_6, - $K_7 = SDLK_7, - $K_8 = SDLK_8, - $K_9 = SDLK_9, - $K_COLON = SDLK_COLON, - $K_SEMICOLON = SDLK_SEMICOLON, - $K_LESS = SDLK_LESS, - $K_EQUALS = SDLK_EQUALS, - $K_GREATER = SDLK_GREATER, - $K_QUESTION = SDLK_QUESTION, - $K_AT = SDLK_AT, - $K_LEFTBRACKET = SDLK_LEFTBRACKET, - $K_BACKSLASH = SDLK_BACKSLASH, - $K_RIGHTBRACKET = SDLK_RIGHTBRACKET, - $K_CARET = SDLK_CARET, - $K_UNDERSCORE = SDLK_UNDERSCORE, - $K_BACKQUOTE = SDLK_BACKQUOTE, - $K_a = SDLK_a, - $K_b = SDLK_b, - $K_c = SDLK_c, - $K_d = SDLK_d, - $K_e = SDLK_e, - $K_f = SDLK_f, - $K_g = SDLK_g, - $K_h = SDLK_h, - $K_i = SDLK_i, - $K_j = SDLK_j, - $K_k = SDLK_k, - $K_l = SDLK_l, - $K_m = SDLK_m, - $K_n = SDLK_n, - $K_o = SDLK_o, - $K_p = SDLK_p, - $K_q = SDLK_q, - $K_r = SDLK_r, - $K_s = SDLK_s, - $K_t = SDLK_t, - $K_u = SDLK_u, - $K_v = SDLK_v, - $K_w = SDLK_w, - $K_x = SDLK_x, - $K_y = SDLK_y, - $K_z = SDLK_z, - $K_DELETE = SDLK_DELETE, - $K_WORLD_0 = SDLK_WORLD_0, - $K_WORLD_1 = SDLK_WORLD_1, - $K_WORLD_2 = SDLK_WORLD_2, - $K_WORLD_3 = SDLK_WORLD_3, - $K_WORLD_4 = SDLK_WORLD_4, - $K_WORLD_5 = SDLK_WORLD_5, - $K_WORLD_6 = SDLK_WORLD_6, - $K_WORLD_7 = SDLK_WORLD_7, - $K_WORLD_8 = SDLK_WORLD_8, - $K_WORLD_9 = SDLK_WORLD_9, - $K_WORLD_10 = SDLK_WORLD_10, - $K_WORLD_11 = SDLK_WORLD_11, - $K_WORLD_12 = SDLK_WORLD_12, - $K_WORLD_13 = SDLK_WORLD_13, - $K_WORLD_14 = SDLK_WORLD_14, - $K_WORLD_15 = SDLK_WORLD_15, - $K_WORLD_16 = SDLK_WORLD_16, - $K_WORLD_17 = SDLK_WORLD_17, - $K_WORLD_18 = SDLK_WORLD_18, - $K_WORLD_19 = SDLK_WORLD_19, - $K_WORLD_20 = SDLK_WORLD_20, - $K_WORLD_21 = SDLK_WORLD_21, - $K_WORLD_22 = SDLK_WORLD_22, - $K_WORLD_23 = SDLK_WORLD_23, - $K_WORLD_24 = SDLK_WORLD_24, - $K_WORLD_25 = SDLK_WORLD_25, - $K_WORLD_26 = SDLK_WORLD_26, - $K_WORLD_27 = SDLK_WORLD_27, - $K_WORLD_28 = SDLK_WORLD_28, - $K_WORLD_29 = SDLK_WORLD_29, - $K_WORLD_30 = SDLK_WORLD_30, - $K_WORLD_31 = SDLK_WORLD_31, - $K_WORLD_32 = SDLK_WORLD_32, - $K_WORLD_33 = SDLK_WORLD_33, - $K_WORLD_34 = SDLK_WORLD_34, - $K_WORLD_35 = SDLK_WORLD_35, - $K_WORLD_36 = SDLK_WORLD_36, - $K_WORLD_37 = SDLK_WORLD_37, - $K_WORLD_38 = SDLK_WORLD_38, - $K_WORLD_39 = SDLK_WORLD_39, - $K_WORLD_40 = SDLK_WORLD_40, - $K_WORLD_41 = SDLK_WORLD_41, - $K_WORLD_42 = SDLK_WORLD_42, - $K_WORLD_43 = SDLK_WORLD_43, - $K_WORLD_44 = SDLK_WORLD_44, - $K_WORLD_45 = SDLK_WORLD_45, - $K_WORLD_46 = SDLK_WORLD_46, - $K_WORLD_47 = SDLK_WORLD_47, - $K_WORLD_48 = SDLK_WORLD_48, - $K_WORLD_49 = SDLK_WORLD_49, - $K_WORLD_50 = SDLK_WORLD_50, - $K_WORLD_51 = SDLK_WORLD_51, - $K_WORLD_52 = SDLK_WORLD_52, - $K_WORLD_53 = SDLK_WORLD_53, - $K_WORLD_54 = SDLK_WORLD_54, - $K_WORLD_55 = SDLK_WORLD_55, - $K_WORLD_56 = SDLK_WORLD_56, - $K_WORLD_57 = SDLK_WORLD_57, - $K_WORLD_58 = SDLK_WORLD_58, - $K_WORLD_59 = SDLK_WORLD_59, - $K_WORLD_60 = SDLK_WORLD_60, - $K_WORLD_61 = SDLK_WORLD_61, - $K_WORLD_62 = SDLK_WORLD_62, - $K_WORLD_63 = SDLK_WORLD_63, - $K_WORLD_64 = SDLK_WORLD_64, - $K_WORLD_65 = SDLK_WORLD_65, - $K_WORLD_66 = SDLK_WORLD_66, - $K_WORLD_67 = SDLK_WORLD_67, - $K_WORLD_68 = SDLK_WORLD_68, - $K_WORLD_69 = SDLK_WORLD_69, - $K_WORLD_70 = SDLK_WORLD_70, - $K_WORLD_71 = SDLK_WORLD_71, - $K_WORLD_72 = SDLK_WORLD_72, - $K_WORLD_73 = SDLK_WORLD_73, - $K_WORLD_74 = SDLK_WORLD_74, - $K_WORLD_75 = SDLK_WORLD_75, - $K_WORLD_76 = SDLK_WORLD_76, - $K_WORLD_77 = SDLK_WORLD_77, - $K_WORLD_78 = SDLK_WORLD_78, - $K_WORLD_79 = SDLK_WORLD_79, - $K_WORLD_80 = SDLK_WORLD_80, - $K_WORLD_81 = SDLK_WORLD_81, - $K_WORLD_82 = SDLK_WORLD_82, - $K_WORLD_83 = SDLK_WORLD_83, - $K_WORLD_84 = SDLK_WORLD_84, - $K_WORLD_85 = SDLK_WORLD_85, - $K_WORLD_86 = SDLK_WORLD_86, - $K_WORLD_87 = SDLK_WORLD_87, - $K_WORLD_88 = SDLK_WORLD_88, - $K_WORLD_89 = SDLK_WORLD_89, - $K_WORLD_90 = SDLK_WORLD_90, - $K_WORLD_91 = SDLK_WORLD_91, - $K_WORLD_92 = SDLK_WORLD_92, - $K_WORLD_93 = SDLK_WORLD_93, - $K_WORLD_94 = SDLK_WORLD_94, - $K_WORLD_95 = SDLK_WORLD_95, - $K_KP0 = SDLK_KP0, - $K_KP1 = SDLK_KP1, - $K_KP2 = SDLK_KP2, - $K_KP3 = SDLK_KP3, - $K_KP4 = SDLK_KP4, - $K_KP5 = SDLK_KP5, - $K_KP6 = SDLK_KP6, - $K_KP7 = SDLK_KP7, - $K_KP8 = SDLK_KP8, - $K_KP9 = SDLK_KP9, - $K_KP_PERIOD = SDLK_KP_PERIOD, - $K_KP_DIVIDE = SDLK_KP_DIVIDE, - $K_KP_MULTIPLY = SDLK_KP_MULTIPLY, - $K_KP_MINUS = SDLK_KP_MINUS, - $K_KP_PLUS = SDLK_KP_PLUS, - $K_KP_ENTER = SDLK_KP_ENTER, - $K_KP_EQUALS = SDLK_KP_EQUALS, - $K_UP = SDLK_UP, - $K_DOWN = SDLK_DOWN, - $K_RIGHT = SDLK_RIGHT, - $K_LEFT = SDLK_LEFT, - $K_INSERT = SDLK_INSERT, - $K_HOME = SDLK_HOME, - $K_END = SDLK_END, - $K_PAGEUP = SDLK_PAGEUP, - $K_PAGEDOWN = SDLK_PAGEDOWN, - $K_F1 = SDLK_F1, - $K_F2 = SDLK_F2, - $K_F3 = SDLK_F3, - $K_F4 = SDLK_F4, - $K_F5 = SDLK_F5, - $K_F6 = SDLK_F6, - $K_F7 = SDLK_F7, - $K_F8 = SDLK_F8, - $K_F9 = SDLK_F9, - $K_F10 = SDLK_F10, - $K_F11 = SDLK_F11, - $K_F12 = SDLK_F12, - $K_F13 = SDLK_F13, - $K_F14 = SDLK_F14, - $K_F15 = SDLK_F15, - $K_NUMLOCK = SDLK_NUMLOCK, - $K_CAPSLOCK = SDLK_CAPSLOCK, - $K_SCROLLOCK = SDLK_SCROLLOCK, - $K_RSHIFT = SDLK_RSHIFT, - $K_LSHIFT = SDLK_LSHIFT, - $K_RCTRL = SDLK_RCTRL, - $K_LCTRL = SDLK_LCTRL, - $K_RALT = SDLK_RALT, - $K_LALT = SDLK_LALT, - $K_RMETA = SDLK_RMETA, - $K_LMETA = SDLK_LMETA, - $K_LSUPER = SDLK_LSUPER, - $K_RSUPER = SDLK_RSUPER, - $K_MODE = SDLK_MODE, - $K_COMPOSE = SDLK_COMPOSE, - $K_HELP = SDLK_HELP, - $K_PRINT = SDLK_PRINT, - $K_SYSREQ = SDLK_SYSREQ, - $K_BREAK = SDLK_BREAK, - $K_MENU = SDLK_MENU, - $K_POWER = SDLK_POWER, - $K_EURO = SDLK_EURO, - $K_UNDO = SDLK_UNDO, - -// key mods - - $KMOD_NONE = KMOD_NONE, - $KMOD_LSHIFT = KMOD_LSHIFT, - $KMOD_RSHIFT = KMOD_RSHIFT, - $KMOD_LCTRL = KMOD_LCTRL, - $KMOD_RCTRL = KMOD_RCTRL, - $KMOD_LALT = KMOD_LALT, - $KMOD_RALT = KMOD_RALT, - $KMOD_LMETA = KMOD_LMETA, - $KMOD_RMETA = KMOD_RMETA, - $KMOD_NUM = KMOD_NUM, - $KMOD_CAPS = KMOD_CAPS, - $KMOD_MODE = KMOD_MODE, - $KMOD_RESERVED = KMOD_RESERVED, - -// hat states - - $HAT_CENTERED = SDL_HAT_CENTERED, - $HAT_UP = SDL_HAT_UP, - $HAT_RIGHT = SDL_HAT_RIGHT, - $HAT_DOWN = SDL_HAT_DOWN, - $HAT_LEFT = SDL_HAT_LEFT, - $HAT_RIGHTUP = SDL_HAT_RIGHTUP, - $HAT_RIGHTDOWN = SDL_HAT_RIGHTDOWN, - $HAT_LEFTUP = SDL_HAT_LEFTUP, - $HAT_LEFTDOWN = SDL_HAT_LEFTDOWN, -}; - diff --git a/sdl/constants.go b/sdl/constants.go index 98848e1..e648b09 100644 --- a/sdl/constants.go +++ b/sdl/constants.go @@ -1,362 +1,386 @@ -// godefs -g sdl constants.c - -// MACHINE GENERATED - DO NOT EDIT. - package sdl -// Constants +// #cgo pkg-config: sdl +// #include +import "C" + const ( - INIT_AUDIO = 0x10 - INIT_VIDEO = 0x20 - INIT_CDROM = 0x100 - INIT_TIMER = 0x1 - INIT_JOYSTICK = 0x200 - INIT_NOPARACHUTE = 0x100000 - INIT_EVENTTHREAD = 0x1000000 - INIT_EVERYTHING = 0xffff - SWSURFACE = 0 - HWSURFACE = 0x1 - ASYNCBLIT = 0x4 - ANYFORMAT = 0x10000000 - HWPALETTE = 0x20000000 - DOUBLEBUF = 0x40000000 - FULLSCREEN = 0x80000000 - OPENGL = 0x2 - OPENGLBLIT = 0xa - RESIZABLE = 0x10 - NOFRAME = 0x20 - HWACCEL = 0x100 - SRCCOLORKEY = 0x1000 - RLEACCELOK = 0x2000 - RLEACCEL = 0x4000 - SRCALPHA = 0x10000 - PREALLOC = 0x1000000 - YV12_OVERLAY = 0x32315659 - IYUV_OVERLAY = 0x56555949 - YUY2_OVERLAY = 0x32595559 - UYVY_OVERLAY = 0x59565955 - YVYU_OVERLAY = 0x55595659 - LOGPAL = 0x1 - PHYSPAL = 0x2 - GL_RED_SIZE = 0 - GL_GREEN_SIZE = 0x1 - GL_BLUE_SIZE = 0x2 - GL_ALPHA_SIZE = 0x3 - GL_BUFFER_SIZE = 0x4 - GL_DOUBLEBUFFER = 0x5 - GL_DEPTH_SIZE = 0x6 - GL_STENCIL_SIZE = 0x7 - GL_ACCUM_RED_SIZE = 0x8 - GL_ACCUM_GREEN_SIZE = 0x9 - GL_ACCUM_BLUE_SIZE = 0xa - GL_ACCUM_ALPHA_SIZE = 0xb - GL_STEREO = 0xc - GL_MULTISAMPLEBUFFERS = 0xd - GL_MULTISAMPLESAMPLES = 0xe - GL_ACCELERATED_VISUAL = 0xf - GL_SWAP_CONTROL = 0x10 - NOEVENT = 0 - ACTIVEEVENT = 0x1 - KEYDOWN = 0x2 - KEYUP = 0x3 - MOUSEMOTION = 0x4 - MOUSEBUTTONDOWN = 0x5 - MOUSEBUTTONUP = 0x6 - JOYAXISMOTION = 0x7 - JOYBALLMOTION = 0x8 - JOYHATMOTION = 0x9 - JOYBUTTONDOWN = 0xa - JOYBUTTONUP = 0xb - QUIT = 0xc - SYSWMEVENT = 0xd - EVENT_RESERVEDA = 0xe - EVENT_RESERVEDB = 0xf - VIDEORESIZE = 0x10 - VIDEOEXPOSE = 0x11 - EVENT_RESERVED2 = 0x12 - EVENT_RESERVED3 = 0x13 - EVENT_RESERVED4 = 0x14 - EVENT_RESERVED5 = 0x15 - EVENT_RESERVED6 = 0x16 - EVENT_RESERVED7 = 0x17 - USEREVENT = 0x18 - NUMEVENTS = 0x20 - ACTIVEEVENTMASK = 0x2 - KEYDOWNMASK = 0x4 - KEYUPMASK = 0x8 - KEYEVENTMASK = 0xc - MOUSEMOTIONMASK = 0x10 - MOUSEBUTTONDOWNMASK = 0x20 - MOUSEBUTTONUPMASK = 0x40 - MOUSEEVENTMASK = 0x70 - JOYAXISMOTIONMASK = 0x80 - JOYBALLMOTIONMASK = 0x100 - JOYHATMOTIONMASK = 0x200 - JOYBUTTONDOWNMASK = 0x400 - JOYBUTTONUPMASK = 0x800 - JOYEVENTMASK = 0xf80 - VIDEORESIZEMASK = 0x10000 - VIDEOEXPOSEMASK = 0x20000 - QUITMASK = 0x1000 - SYSWMEVENTMASK = 0x2000 - QUERY = -0x1 - DISABLE = 0 - ENABLE = 0x1 - K_UNKNOWN = 0 - K_FIRST = 0 - K_BACKSPACE = 0x8 - K_TAB = 0x9 - K_CLEAR = 0xc - K_RETURN = 0xd - K_PAUSE = 0x13 - K_ESCAPE = 0x1b - K_SPACE = 0x20 - K_EXCLAIM = 0x21 - K_QUOTEDBL = 0x22 - K_HASH = 0x23 - K_DOLLAR = 0x24 - K_AMPERSAND = 0x26 - K_QUOTE = 0x27 - K_LEFTPAREN = 0x28 - K_RIGHTPAREN = 0x29 - K_ASTERISK = 0x2a - K_PLUS = 0x2b - K_COMMA = 0x2c - K_MINUS = 0x2d - K_PERIOD = 0x2e - K_SLASH = 0x2f - K_0 = 0x30 - K_1 = 0x31 - K_2 = 0x32 - K_3 = 0x33 - K_4 = 0x34 - K_5 = 0x35 - K_6 = 0x36 - K_7 = 0x37 - K_8 = 0x38 - K_9 = 0x39 - K_COLON = 0x3a - K_SEMICOLON = 0x3b - K_LESS = 0x3c - K_EQUALS = 0x3d - K_GREATER = 0x3e - K_QUESTION = 0x3f - K_AT = 0x40 - K_LEFTBRACKET = 0x5b - K_BACKSLASH = 0x5c - K_RIGHTBRACKET = 0x5d - K_CARET = 0x5e - K_UNDERSCORE = 0x5f - K_BACKQUOTE = 0x60 - K_a = 0x61 - K_b = 0x62 - K_c = 0x63 - K_d = 0x64 - K_e = 0x65 - K_f = 0x66 - K_g = 0x67 - K_h = 0x68 - K_i = 0x69 - K_j = 0x6a - K_k = 0x6b - K_l = 0x6c - K_m = 0x6d - K_n = 0x6e - K_o = 0x6f - K_p = 0x70 - K_q = 0x71 - K_r = 0x72 - K_s = 0x73 - K_t = 0x74 - K_u = 0x75 - K_v = 0x76 - K_w = 0x77 - K_x = 0x78 - K_y = 0x79 - K_z = 0x7a - K_DELETE = 0x7f - K_WORLD_0 = 0xa0 - K_WORLD_1 = 0xa1 - K_WORLD_2 = 0xa2 - K_WORLD_3 = 0xa3 - K_WORLD_4 = 0xa4 - K_WORLD_5 = 0xa5 - K_WORLD_6 = 0xa6 - K_WORLD_7 = 0xa7 - K_WORLD_8 = 0xa8 - K_WORLD_9 = 0xa9 - K_WORLD_10 = 0xaa - K_WORLD_11 = 0xab - K_WORLD_12 = 0xac - K_WORLD_13 = 0xad - K_WORLD_14 = 0xae - K_WORLD_15 = 0xaf - K_WORLD_16 = 0xb0 - K_WORLD_17 = 0xb1 - K_WORLD_18 = 0xb2 - K_WORLD_19 = 0xb3 - K_WORLD_20 = 0xb4 - K_WORLD_21 = 0xb5 - K_WORLD_22 = 0xb6 - K_WORLD_23 = 0xb7 - K_WORLD_24 = 0xb8 - K_WORLD_25 = 0xb9 - K_WORLD_26 = 0xba - K_WORLD_27 = 0xbb - K_WORLD_28 = 0xbc - K_WORLD_29 = 0xbd - K_WORLD_30 = 0xbe - K_WORLD_31 = 0xbf - K_WORLD_32 = 0xc0 - K_WORLD_33 = 0xc1 - K_WORLD_34 = 0xc2 - K_WORLD_35 = 0xc3 - K_WORLD_36 = 0xc4 - K_WORLD_37 = 0xc5 - K_WORLD_38 = 0xc6 - K_WORLD_39 = 0xc7 - K_WORLD_40 = 0xc8 - K_WORLD_41 = 0xc9 - K_WORLD_42 = 0xca - K_WORLD_43 = 0xcb - K_WORLD_44 = 0xcc - K_WORLD_45 = 0xcd - K_WORLD_46 = 0xce - K_WORLD_47 = 0xcf - K_WORLD_48 = 0xd0 - K_WORLD_49 = 0xd1 - K_WORLD_50 = 0xd2 - K_WORLD_51 = 0xd3 - K_WORLD_52 = 0xd4 - K_WORLD_53 = 0xd5 - K_WORLD_54 = 0xd6 - K_WORLD_55 = 0xd7 - K_WORLD_56 = 0xd8 - K_WORLD_57 = 0xd9 - K_WORLD_58 = 0xda - K_WORLD_59 = 0xdb - K_WORLD_60 = 0xdc - K_WORLD_61 = 0xdd - K_WORLD_62 = 0xde - K_WORLD_63 = 0xdf - K_WORLD_64 = 0xe0 - K_WORLD_65 = 0xe1 - K_WORLD_66 = 0xe2 - K_WORLD_67 = 0xe3 - K_WORLD_68 = 0xe4 - K_WORLD_69 = 0xe5 - K_WORLD_70 = 0xe6 - K_WORLD_71 = 0xe7 - K_WORLD_72 = 0xe8 - K_WORLD_73 = 0xe9 - K_WORLD_74 = 0xea - K_WORLD_75 = 0xeb - K_WORLD_76 = 0xec - K_WORLD_77 = 0xed - K_WORLD_78 = 0xee - K_WORLD_79 = 0xef - K_WORLD_80 = 0xf0 - K_WORLD_81 = 0xf1 - K_WORLD_82 = 0xf2 - K_WORLD_83 = 0xf3 - K_WORLD_84 = 0xf4 - K_WORLD_85 = 0xf5 - K_WORLD_86 = 0xf6 - K_WORLD_87 = 0xf7 - K_WORLD_88 = 0xf8 - K_WORLD_89 = 0xf9 - K_WORLD_90 = 0xfa - K_WORLD_91 = 0xfb - K_WORLD_92 = 0xfc - K_WORLD_93 = 0xfd - K_WORLD_94 = 0xfe - K_WORLD_95 = 0xff - K_KP0 = 0x100 - K_KP1 = 0x101 - K_KP2 = 0x102 - K_KP3 = 0x103 - K_KP4 = 0x104 - K_KP5 = 0x105 - K_KP6 = 0x106 - K_KP7 = 0x107 - K_KP8 = 0x108 - K_KP9 = 0x109 - K_KP_PERIOD = 0x10a - K_KP_DIVIDE = 0x10b - K_KP_MULTIPLY = 0x10c - K_KP_MINUS = 0x10d - K_KP_PLUS = 0x10e - K_KP_ENTER = 0x10f - K_KP_EQUALS = 0x110 - K_UP = 0x111 - K_DOWN = 0x112 - K_RIGHT = 0x113 - K_LEFT = 0x114 - K_INSERT = 0x115 - K_HOME = 0x116 - K_END = 0x117 - K_PAGEUP = 0x118 - K_PAGEDOWN = 0x119 - K_F1 = 0x11a - K_F2 = 0x11b - K_F3 = 0x11c - K_F4 = 0x11d - K_F5 = 0x11e - K_F6 = 0x11f - K_F7 = 0x120 - K_F8 = 0x121 - K_F9 = 0x122 - K_F10 = 0x123 - K_F11 = 0x124 - K_F12 = 0x125 - K_F13 = 0x126 - K_F14 = 0x127 - K_F15 = 0x128 - K_NUMLOCK = 0x12c - K_CAPSLOCK = 0x12d - K_SCROLLOCK = 0x12e - K_RSHIFT = 0x12f - K_LSHIFT = 0x130 - K_RCTRL = 0x131 - K_LCTRL = 0x132 - K_RALT = 0x133 - K_LALT = 0x134 - K_RMETA = 0x135 - K_LMETA = 0x136 - K_LSUPER = 0x137 - K_RSUPER = 0x138 - K_MODE = 0x139 - K_COMPOSE = 0x13a - K_HELP = 0x13b - K_PRINT = 0x13c - K_SYSREQ = 0x13d - K_BREAK = 0x13e - K_MENU = 0x13f - K_POWER = 0x140 - K_EURO = 0x141 - K_UNDO = 0x142 - KMOD_NONE = 0 - KMOD_LSHIFT = 0x1 - KMOD_RSHIFT = 0x2 - KMOD_LCTRL = 0x40 - KMOD_RCTRL = 0x80 - KMOD_LALT = 0x100 - KMOD_RALT = 0x200 - KMOD_LMETA = 0x400 - KMOD_RMETA = 0x800 - KMOD_NUM = 0x1000 - KMOD_CAPS = 0x2000 - KMOD_MODE = 0x4000 - KMOD_RESERVED = 0x8000 - HAT_CENTERED = 0 - HAT_UP = 0x1 - HAT_RIGHT = 0x2 - HAT_DOWN = 0x4 - HAT_LEFT = 0x8 - HAT_RIGHTUP = 0x3 - HAT_RIGHTDOWN = 0x6 - HAT_LEFTUP = 0x9 - HAT_LEFTDOWN = 0xc -) + // init flags + + INIT_AUDIO = C.SDL_INIT_AUDIO + INIT_VIDEO = C.SDL_INIT_VIDEO + INIT_CDROM = C.SDL_INIT_CDROM + INIT_TIMER = C.SDL_INIT_TIMER + INIT_JOYSTICK = C.SDL_INIT_JOYSTICK + INIT_NOPARACHUTE = C.SDL_INIT_NOPARACHUTE + INIT_EVENTTHREAD = C.SDL_INIT_EVENTTHREAD + INIT_EVERYTHING = C.SDL_INIT_EVERYTHING + + // setvideo flags + + SWSURFACE = C.SDL_SWSURFACE + HWSURFACE = C.SDL_HWSURFACE + ASYNCBLIT = C.SDL_ASYNCBLIT + ANYFORMAT = C.SDL_ANYFORMAT + HWPALETTE = C.SDL_HWPALETTE + DOUBLEBUF = C.SDL_DOUBLEBUF + FULLSCREEN = C.SDL_FULLSCREEN + OPENGL = C.SDL_OPENGL + OPENGLBLIT = C.SDL_OPENGLBLIT + RESIZABLE = C.SDL_RESIZABLE + NOFRAME = C.SDL_NOFRAME + HWACCEL = C.SDL_HWACCEL + SRCCOLORKEY = C.SDL_SRCCOLORKEY + RLEACCELOK = C.SDL_RLEACCELOK + RLEACCEL = C.SDL_RLEACCEL + SRCALPHA = C.SDL_SRCALPHA + PREALLOC = C.SDL_PREALLOC + YV12_OVERLAY = C.SDL_YV12_OVERLAY + IYUV_OVERLAY = C.SDL_IYUV_OVERLAY + YUY2_OVERLAY = C.SDL_YUY2_OVERLAY + UYVY_OVERLAY = C.SDL_UYVY_OVERLAY + YVYU_OVERLAY = C.SDL_YVYU_OVERLAY + LOGPAL = C.SDL_LOGPAL + PHYSPAL = C.SDL_PHYSPAL + + // More setvideo flags: GLattr enumeration + + GL_RED_SIZE = C.SDL_GL_RED_SIZE + GL_GREEN_SIZE = C.SDL_GL_GREEN_SIZE + GL_BLUE_SIZE = C.SDL_GL_BLUE_SIZE + GL_ALPHA_SIZE = C.SDL_GL_ALPHA_SIZE + GL_BUFFER_SIZE = C.SDL_GL_BUFFER_SIZE + GL_DOUBLEBUFFER = C.SDL_GL_DOUBLEBUFFER + GL_DEPTH_SIZE = C.SDL_GL_DEPTH_SIZE + GL_STENCIL_SIZE = C.SDL_GL_STENCIL_SIZE + GL_ACCUM_RED_SIZE = C.SDL_GL_ACCUM_RED_SIZE + GL_ACCUM_GREEN_SIZE = C.SDL_GL_ACCUM_GREEN_SIZE + GL_ACCUM_BLUE_SIZE = C.SDL_GL_ACCUM_BLUE_SIZE + GL_ACCUM_ALPHA_SIZE = C.SDL_GL_ACCUM_ALPHA_SIZE + GL_STEREO = C.SDL_GL_STEREO + GL_MULTISAMPLEBUFFERS = C.SDL_GL_MULTISAMPLEBUFFERS + GL_MULTISAMPLESAMPLES = C.SDL_GL_MULTISAMPLESAMPLES + GL_ACCELERATED_VISUAL = C.SDL_GL_ACCELERATED_VISUAL + GL_SWAP_CONTROL = C.SDL_GL_SWAP_CONTROL + + // event types + + NOEVENT = C.SDL_NOEVENT + ACTIVEEVENT = C.SDL_ACTIVEEVENT + KEYDOWN = C.SDL_KEYDOWN + KEYUP = C.SDL_KEYUP + MOUSEMOTION = C.SDL_MOUSEMOTION + MOUSEBUTTONDOWN = C.SDL_MOUSEBUTTONDOWN + MOUSEBUTTONUP = C.SDL_MOUSEBUTTONUP + JOYAXISMOTION = C.SDL_JOYAXISMOTION + JOYBALLMOTION = C.SDL_JOYBALLMOTION + JOYHATMOTION = C.SDL_JOYHATMOTION + JOYBUTTONDOWN = C.SDL_JOYBUTTONDOWN + JOYBUTTONUP = C.SDL_JOYBUTTONUP + QUIT = C.SDL_QUIT + SYSWMEVENT = C.SDL_SYSWMEVENT + EVENT_RESERVEDA = C.SDL_EVENT_RESERVEDA + EVENT_RESERVEDB = C.SDL_EVENT_RESERVEDB + VIDEORESIZE = C.SDL_VIDEORESIZE + VIDEOEXPOSE = C.SDL_VIDEOEXPOSE + EVENT_RESERVED2 = C.SDL_EVENT_RESERVED2 + EVENT_RESERVED3 = C.SDL_EVENT_RESERVED3 + EVENT_RESERVED4 = C.SDL_EVENT_RESERVED4 + EVENT_RESERVED5 = C.SDL_EVENT_RESERVED5 + EVENT_RESERVED6 = C.SDL_EVENT_RESERVED6 + EVENT_RESERVED7 = C.SDL_EVENT_RESERVED7 -// Types + USEREVENT = C.SDL_USEREVENT + + NUMEVENTS = C.SDL_NUMEVENTS + + // event masks + + ACTIVEEVENTMASK = C.SDL_ACTIVEEVENTMASK + KEYDOWNMASK = C.SDL_KEYDOWNMASK + KEYUPMASK = C.SDL_KEYUPMASK + KEYEVENTMASK = C.SDL_KEYEVENTMASK + MOUSEMOTIONMASK = C.SDL_MOUSEMOTIONMASK + MOUSEBUTTONDOWNMASK = C.SDL_MOUSEBUTTONDOWNMASK + MOUSEBUTTONUPMASK = C.SDL_MOUSEBUTTONUPMASK + MOUSEEVENTMASK = C.SDL_MOUSEEVENTMASK + JOYAXISMOTIONMASK = C.SDL_JOYAXISMOTIONMASK + JOYBALLMOTIONMASK = C.SDL_JOYBALLMOTIONMASK + JOYHATMOTIONMASK = C.SDL_JOYHATMOTIONMASK + JOYBUTTONDOWNMASK = C.SDL_JOYBUTTONDOWNMASK + JOYBUTTONUPMASK = C.SDL_JOYBUTTONUPMASK + JOYEVENTMASK = C.SDL_JOYEVENTMASK + VIDEORESIZEMASK = C.SDL_VIDEORESIZEMASK + VIDEOEXPOSEMASK = C.SDL_VIDEOEXPOSEMASK + QUITMASK = C.SDL_QUITMASK + SYSWMEVENTMASK = C.SDL_SYSWMEVENTMASK + + // event state + + QUERY = C.SDL_QUERY + DISABLE = C.SDL_DISABLE + ENABLE = C.SDL_ENABLE + + // keys + K_UNKNOWN = C.SDLK_UNKNOWN + K_FIRST = C.SDLK_FIRST + K_BACKSPACE = C.SDLK_BACKSPACE + K_TAB = C.SDLK_TAB + K_CLEAR = C.SDLK_CLEAR + K_RETURN = C.SDLK_RETURN + K_PAUSE = C.SDLK_PAUSE + K_ESCAPE = C.SDLK_ESCAPE + K_SPACE = C.SDLK_SPACE + K_EXCLAIM = C.SDLK_EXCLAIM + K_QUOTEDBL = C.SDLK_QUOTEDBL + K_HASH = C.SDLK_HASH + K_DOLLAR = C.SDLK_DOLLAR + K_AMPERSAND = C.SDLK_AMPERSAND + K_QUOTE = C.SDLK_QUOTE + K_LEFTPAREN = C.SDLK_LEFTPAREN + K_RIGHTPAREN = C.SDLK_RIGHTPAREN + K_ASTERISK = C.SDLK_ASTERISK + K_PLUS = C.SDLK_PLUS + K_COMMA = C.SDLK_COMMA + K_MINUS = C.SDLK_MINUS + K_PERIOD = C.SDLK_PERIOD + K_SLASH = C.SDLK_SLASH + K_0 = C.SDLK_0 + K_1 = C.SDLK_1 + K_2 = C.SDLK_2 + K_3 = C.SDLK_3 + K_4 = C.SDLK_4 + K_5 = C.SDLK_5 + K_6 = C.SDLK_6 + K_7 = C.SDLK_7 + K_8 = C.SDLK_8 + K_9 = C.SDLK_9 + K_COLON = C.SDLK_COLON + K_SEMICOLON = C.SDLK_SEMICOLON + K_LESS = C.SDLK_LESS + K_EQUALS = C.SDLK_EQUALS + K_GREATER = C.SDLK_GREATER + K_QUESTION = C.SDLK_QUESTION + K_AT = C.SDLK_AT + K_LEFTBRACKET = C.SDLK_LEFTBRACKET + K_BACKSLASH = C.SDLK_BACKSLASH + K_RIGHTBRACKET = C.SDLK_RIGHTBRACKET + K_CARET = C.SDLK_CARET + K_UNDERSCORE = C.SDLK_UNDERSCORE + K_BACKQUOTE = C.SDLK_BACKQUOTE + K_a = C.SDLK_a + K_b = C.SDLK_b + K_c = C.SDLK_c + K_d = C.SDLK_d + K_e = C.SDLK_e + K_f = C.SDLK_f + K_g = C.SDLK_g + K_h = C.SDLK_h + K_i = C.SDLK_i + K_j = C.SDLK_j + K_k = C.SDLK_k + K_l = C.SDLK_l + K_m = C.SDLK_m + K_n = C.SDLK_n + K_o = C.SDLK_o + K_p = C.SDLK_p + K_q = C.SDLK_q + K_r = C.SDLK_r + K_s = C.SDLK_s + K_t = C.SDLK_t + K_u = C.SDLK_u + K_v = C.SDLK_v + K_w = C.SDLK_w + K_x = C.SDLK_x + K_y = C.SDLK_y + K_z = C.SDLK_z + K_DELETE = C.SDLK_DELETE + K_WORLD_0 = C.SDLK_WORLD_0 + K_WORLD_1 = C.SDLK_WORLD_1 + K_WORLD_2 = C.SDLK_WORLD_2 + K_WORLD_3 = C.SDLK_WORLD_3 + K_WORLD_4 = C.SDLK_WORLD_4 + K_WORLD_5 = C.SDLK_WORLD_5 + K_WORLD_6 = C.SDLK_WORLD_6 + K_WORLD_7 = C.SDLK_WORLD_7 + K_WORLD_8 = C.SDLK_WORLD_8 + K_WORLD_9 = C.SDLK_WORLD_9 + K_WORLD_10 = C.SDLK_WORLD_10 + K_WORLD_11 = C.SDLK_WORLD_11 + K_WORLD_12 = C.SDLK_WORLD_12 + K_WORLD_13 = C.SDLK_WORLD_13 + K_WORLD_14 = C.SDLK_WORLD_14 + K_WORLD_15 = C.SDLK_WORLD_15 + K_WORLD_16 = C.SDLK_WORLD_16 + K_WORLD_17 = C.SDLK_WORLD_17 + K_WORLD_18 = C.SDLK_WORLD_18 + K_WORLD_19 = C.SDLK_WORLD_19 + K_WORLD_20 = C.SDLK_WORLD_20 + K_WORLD_21 = C.SDLK_WORLD_21 + K_WORLD_22 = C.SDLK_WORLD_22 + K_WORLD_23 = C.SDLK_WORLD_23 + K_WORLD_24 = C.SDLK_WORLD_24 + K_WORLD_25 = C.SDLK_WORLD_25 + K_WORLD_26 = C.SDLK_WORLD_26 + K_WORLD_27 = C.SDLK_WORLD_27 + K_WORLD_28 = C.SDLK_WORLD_28 + K_WORLD_29 = C.SDLK_WORLD_29 + K_WORLD_30 = C.SDLK_WORLD_30 + K_WORLD_31 = C.SDLK_WORLD_31 + K_WORLD_32 = C.SDLK_WORLD_32 + K_WORLD_33 = C.SDLK_WORLD_33 + K_WORLD_34 = C.SDLK_WORLD_34 + K_WORLD_35 = C.SDLK_WORLD_35 + K_WORLD_36 = C.SDLK_WORLD_36 + K_WORLD_37 = C.SDLK_WORLD_37 + K_WORLD_38 = C.SDLK_WORLD_38 + K_WORLD_39 = C.SDLK_WORLD_39 + K_WORLD_40 = C.SDLK_WORLD_40 + K_WORLD_41 = C.SDLK_WORLD_41 + K_WORLD_42 = C.SDLK_WORLD_42 + K_WORLD_43 = C.SDLK_WORLD_43 + K_WORLD_44 = C.SDLK_WORLD_44 + K_WORLD_45 = C.SDLK_WORLD_45 + K_WORLD_46 = C.SDLK_WORLD_46 + K_WORLD_47 = C.SDLK_WORLD_47 + K_WORLD_48 = C.SDLK_WORLD_48 + K_WORLD_49 = C.SDLK_WORLD_49 + K_WORLD_50 = C.SDLK_WORLD_50 + K_WORLD_51 = C.SDLK_WORLD_51 + K_WORLD_52 = C.SDLK_WORLD_52 + K_WORLD_53 = C.SDLK_WORLD_53 + K_WORLD_54 = C.SDLK_WORLD_54 + K_WORLD_55 = C.SDLK_WORLD_55 + K_WORLD_56 = C.SDLK_WORLD_56 + K_WORLD_57 = C.SDLK_WORLD_57 + K_WORLD_58 = C.SDLK_WORLD_58 + K_WORLD_59 = C.SDLK_WORLD_59 + K_WORLD_60 = C.SDLK_WORLD_60 + K_WORLD_61 = C.SDLK_WORLD_61 + K_WORLD_62 = C.SDLK_WORLD_62 + K_WORLD_63 = C.SDLK_WORLD_63 + K_WORLD_64 = C.SDLK_WORLD_64 + K_WORLD_65 = C.SDLK_WORLD_65 + K_WORLD_66 = C.SDLK_WORLD_66 + K_WORLD_67 = C.SDLK_WORLD_67 + K_WORLD_68 = C.SDLK_WORLD_68 + K_WORLD_69 = C.SDLK_WORLD_69 + K_WORLD_70 = C.SDLK_WORLD_70 + K_WORLD_71 = C.SDLK_WORLD_71 + K_WORLD_72 = C.SDLK_WORLD_72 + K_WORLD_73 = C.SDLK_WORLD_73 + K_WORLD_74 = C.SDLK_WORLD_74 + K_WORLD_75 = C.SDLK_WORLD_75 + K_WORLD_76 = C.SDLK_WORLD_76 + K_WORLD_77 = C.SDLK_WORLD_77 + K_WORLD_78 = C.SDLK_WORLD_78 + K_WORLD_79 = C.SDLK_WORLD_79 + K_WORLD_80 = C.SDLK_WORLD_80 + K_WORLD_81 = C.SDLK_WORLD_81 + K_WORLD_82 = C.SDLK_WORLD_82 + K_WORLD_83 = C.SDLK_WORLD_83 + K_WORLD_84 = C.SDLK_WORLD_84 + K_WORLD_85 = C.SDLK_WORLD_85 + K_WORLD_86 = C.SDLK_WORLD_86 + K_WORLD_87 = C.SDLK_WORLD_87 + K_WORLD_88 = C.SDLK_WORLD_88 + K_WORLD_89 = C.SDLK_WORLD_89 + K_WORLD_90 = C.SDLK_WORLD_90 + K_WORLD_91 = C.SDLK_WORLD_91 + K_WORLD_92 = C.SDLK_WORLD_92 + K_WORLD_93 = C.SDLK_WORLD_93 + K_WORLD_94 = C.SDLK_WORLD_94 + K_WORLD_95 = C.SDLK_WORLD_95 + K_KP0 = C.SDLK_KP0 + K_KP1 = C.SDLK_KP1 + K_KP2 = C.SDLK_KP2 + K_KP3 = C.SDLK_KP3 + K_KP4 = C.SDLK_KP4 + K_KP5 = C.SDLK_KP5 + K_KP6 = C.SDLK_KP6 + K_KP7 = C.SDLK_KP7 + K_KP8 = C.SDLK_KP8 + K_KP9 = C.SDLK_KP9 + K_KP_PERIOD = C.SDLK_KP_PERIOD + K_KP_DIVIDE = C.SDLK_KP_DIVIDE + K_KP_MULTIPLY = C.SDLK_KP_MULTIPLY + K_KP_MINUS = C.SDLK_KP_MINUS + K_KP_PLUS = C.SDLK_KP_PLUS + K_KP_ENTER = C.SDLK_KP_ENTER + K_KP_EQUALS = C.SDLK_KP_EQUALS + K_UP = C.SDLK_UP + K_DOWN = C.SDLK_DOWN + K_RIGHT = C.SDLK_RIGHT + K_LEFT = C.SDLK_LEFT + K_INSERT = C.SDLK_INSERT + K_HOME = C.SDLK_HOME + K_END = C.SDLK_END + K_PAGEUP = C.SDLK_PAGEUP + K_PAGEDOWN = C.SDLK_PAGEDOWN + K_F1 = C.SDLK_F1 + K_F2 = C.SDLK_F2 + K_F3 = C.SDLK_F3 + K_F4 = C.SDLK_F4 + K_F5 = C.SDLK_F5 + K_F6 = C.SDLK_F6 + K_F7 = C.SDLK_F7 + K_F8 = C.SDLK_F8 + K_F9 = C.SDLK_F9 + K_F10 = C.SDLK_F10 + K_F11 = C.SDLK_F11 + K_F12 = C.SDLK_F12 + K_F13 = C.SDLK_F13 + K_F14 = C.SDLK_F14 + K_F15 = C.SDLK_F15 + K_NUMLOCK = C.SDLK_NUMLOCK + K_CAPSLOCK = C.SDLK_CAPSLOCK + K_SCROLLOCK = C.SDLK_SCROLLOCK + K_RSHIFT = C.SDLK_RSHIFT + K_LSHIFT = C.SDLK_LSHIFT + K_RCTRL = C.SDLK_RCTRL + K_LCTRL = C.SDLK_LCTRL + K_RALT = C.SDLK_RALT + K_LALT = C.SDLK_LALT + K_RMETA = C.SDLK_RMETA + K_LMETA = C.SDLK_LMETA + K_LSUPER = C.SDLK_LSUPER + K_RSUPER = C.SDLK_RSUPER + K_MODE = C.SDLK_MODE + K_COMPOSE = C.SDLK_COMPOSE + K_HELP = C.SDLK_HELP + K_PRINT = C.SDLK_PRINT + K_SYSREQ = C.SDLK_SYSREQ + K_BREAK = C.SDLK_BREAK + K_MENU = C.SDLK_MENU + K_POWER = C.SDLK_POWER + K_EURO = C.SDLK_EURO + K_UNDO = C.SDLK_UNDO + + // key mods + + KMOD_NONE = C.KMOD_NONE + KMOD_LSHIFT = C.KMOD_LSHIFT + KMOD_RSHIFT = C.KMOD_RSHIFT + KMOD_LCTRL = C.KMOD_LCTRL + KMOD_RCTRL = C.KMOD_RCTRL + KMOD_LALT = C.KMOD_LALT + KMOD_RALT = C.KMOD_RALT + KMOD_LMETA = C.KMOD_LMETA + KMOD_RMETA = C.KMOD_RMETA + KMOD_NUM = C.KMOD_NUM + KMOD_CAPS = C.KMOD_CAPS + KMOD_MODE = C.KMOD_MODE + KMOD_RESERVED = C.KMOD_RESERVED + + // hat states + + HAT_CENTERED = C.SDL_HAT_CENTERED + HAT_UP = C.SDL_HAT_UP + HAT_RIGHT = C.SDL_HAT_RIGHT + HAT_DOWN = C.SDL_HAT_DOWN + HAT_LEFT = C.SDL_HAT_LEFT + HAT_RIGHTUP = C.SDL_HAT_RIGHTUP + HAT_RIGHTDOWN = C.SDL_HAT_RIGHTDOWN + HAT_LEFTUP = C.SDL_HAT_LEFTUP + HAT_LEFTDOWN = C.SDL_HAT_LEFTDOWN +) diff --git a/sdl/structs.8.go b/sdl/structs_386.go similarity index 100% rename from sdl/structs.8.go rename to sdl/structs_386.go diff --git a/sdl/structs.6.go b/sdl/structs_amd64.go similarity index 100% rename from sdl/structs.6.go rename to sdl/structs_amd64.go diff --git a/test/Makefile b/test/Makefile deleted file mode 100644 index 4670fb3..0000000 --- a/test/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=test -GOFILES=test.go - -include $(GOROOT)/src/Make.cmd diff --git a/ttf/Makefile b/ttf/Makefile deleted file mode 100644 index 2443ca4..0000000 --- a/ttf/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=atom/sdl/ttf - -GOFILES:=constants.go -CGOFILES:=ttf.go -CGO_LDFLAGS:=-lSDL_ttf - -CLEANFILES+=ttf - -include $(GOROOT)/src/Make.pkg diff --git a/ttf/constants.go b/ttf/constants.go index 157f774..9c0d01b 100644 --- a/ttf/constants.go +++ b/ttf/constants.go @@ -1,6 +1,5 @@ package ttf - const ( STYLE_NORMAL = 0 STYLE_BOLD = 0x1 diff --git a/ttf/ttf.go b/ttf/ttf.go index 68bf6b8..25412b6 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -10,9 +10,12 @@ package ttf // #cgo pkg-config: SDL_ttf // #include import "C" -import "atom/sdl" -import "sync" -import "unsafe" + +import ( + "github.com/0xe2-0x9a-0x9b/Go-SDL/sdl" + "sync" + "unsafe" +) // The version of Go-SDL TTF bindings. // The version descriptor changes into a new unique string From a121788d5d2e3cf43ed99edf24a23dbf127c17d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 22 Feb 2012 09:35:59 +0100 Subject: [PATCH 40/79] Add documentation --- sdl/audio/audio.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 058d2b3..553f779 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -5,6 +5,9 @@ * except for usages in immoral contexts. */ +/* +An interface to low-level SDL sound functions. +*/ package audio // #cgo pkg-config: sdl From 907dcec75ba70962c1c855a7239ca02c8f7c7216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 7 Mar 2012 09:21:41 +0100 Subject: [PATCH 41/79] Fix installation procedure in README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 741a104..5c277bc 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,8 @@ Make sure you have SDL, SDL-image, SDL-mixer and SDL-ttf (all in -dev version). Installing libraries and examples: - go get -v github.com/0xe2-0x9a-0x9b/Go-SDL/... + go get -d -v github.com/0xe2-0x9a-0x9b/Go-SDL + go install -v github.com/0xe2-0x9a-0x9b/Go-SDL/... # Credits From 22a4451432372b1e70c6fa76edfbc62161173391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Tue, 13 Mar 2012 16:44:47 +0100 Subject: [PATCH 42/79] Unfix installation procedure in README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 5c277bc..741a104 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,7 @@ Make sure you have SDL, SDL-image, SDL-mixer and SDL-ttf (all in -dev version). Installing libraries and examples: - go get -d -v github.com/0xe2-0x9a-0x9b/Go-SDL - go install -v github.com/0xe2-0x9a-0x9b/Go-SDL/... + go get -v github.com/0xe2-0x9a-0x9b/Go-SDL/... # Credits From 77a8d9e9a89ee46e1b48cd8296340381d2276c3f Mon Sep 17 00:00:00 2001 From: Yves Junqueira Date: Tue, 17 Apr 2012 23:49:39 +0200 Subject: [PATCH 43/79] gofmt --- sdl/sdl.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index f14e39f..0d18594 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -7,7 +7,6 @@ flavor (eg. Rather than sdl.Flip(surface) it's surface.Flip() ) */ package sdl - // #cgo pkg-config: sdl SDL_image // // struct private_hwdata{}; @@ -84,7 +83,6 @@ func (s *Surface) destroy() { s.Pixels = nil } - // ======= // General // ======= @@ -146,7 +144,6 @@ func WasInit(flags uint32) int { return status } - // ============== // Error Handling // ============== @@ -177,7 +174,6 @@ func ClearError() { GlobalMutex.Unlock() } - // ====== // Video // ====== @@ -544,7 +540,6 @@ func (s *Surface) DisplayFormat() *Surface { return wrap(p) } - // ======== // Keyboard // ======== @@ -623,7 +618,6 @@ func GetKeyName(key Key) string { return name } - // ====== // Events // ====== @@ -645,7 +639,6 @@ func (event *Event) poll() bool { return ret != 0 } - // ===== // Mouse // ===== @@ -675,7 +668,6 @@ func ShowCursor(toggle int) int { return state } - // ======== // Joystick // ======== From bff97f10d56122de6144773b6a000e3e84828dc4 Mon Sep 17 00:00:00 2001 From: Yves Junqueira Date: Tue, 17 Apr 2012 23:51:48 +0200 Subject: [PATCH 44/79] Add SaveBMP --- sdl/sdl.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sdl/sdl.go b/sdl/sdl.go index 0d18594..7d44bb4 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -16,6 +16,7 @@ package sdl // #include // #include // static void SetError(const char* description){SDL_SetError("%s",description);} +// static int __SDL_SaveBMP(SDL_Surface *surface, const char *file) { return SDL_SaveBMP(surface, file); } import "C" import "unsafe" import "sync" @@ -520,6 +521,17 @@ func Load(file string) *Surface { return wrap(screen) } +// SaveBMP saves the src surface as a Windows BMP to file. +func (src *Surface) SaveBMP(file string) int { + GlobalMutex.Lock() + cfile := C.CString(file) + // SDL_SaveBMP is a macro. + res := int(C.__SDL_SaveBMP(src.cSurface, cfile)) + C.free(unsafe.Pointer(cfile)) + GlobalMutex.Unlock() + return res +} + // Creates an empty Surface. func CreateRGBSurface(flags uint32, width int, height int, bpp int, Rmask uint32, Gmask uint32, Bmask uint32, Amask uint32) *Surface { GlobalMutex.Lock() From e511ba7b3cf65e5d550ff2b558f8936234517caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Mon, 7 May 2012 04:35:32 +0200 Subject: [PATCH 45/79] Fix compilation with older SDL packages which may be missing some pkg-config files --- mixer/mixer.go | 3 ++- sdl/sdl.go | 3 ++- ttf/ttf.go | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mixer/mixer.go b/mixer/mixer.go index 0ae3ebc..c0bdb8a 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -7,7 +7,8 @@ functions have been changed to be in a more object-oriented style */ package mixer -// #cgo pkg-config: SDL_mixer +// #cgo pkg-config: sdl +// #cgo LDFLAGS: -lSDL_mixer // #include import "C" import "unsafe" diff --git a/sdl/sdl.go b/sdl/sdl.go index 7d44bb4..18f26fe 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -7,7 +7,8 @@ flavor (eg. Rather than sdl.Flip(surface) it's surface.Flip() ) */ package sdl -// #cgo pkg-config: sdl SDL_image +// #cgo pkg-config: sdl +// #cgo LDFLAGS: -lSDL_image // // struct private_hwdata{}; // struct SDL_BlitMap{}; diff --git a/ttf/ttf.go b/ttf/ttf.go index 25412b6..bc9ded9 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -7,7 +7,8 @@ that work with loaded fonts are changed to have a more object-oriented feel. */ package ttf -// #cgo pkg-config: SDL_ttf +// #cgo pkg-config: sdl +// #cgo LDFLAGS: -lSDL_ttf // #include import "C" From 21f86f8f86cc326ec099f39b5b825ead9f71bf2f Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Mon, 7 May 2012 10:14:47 -0400 Subject: [PATCH 46/79] Remove dependency on librt on Darwin. --- sdl/audio/audio.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 553f779..4f0f9ea 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -11,7 +11,6 @@ An interface to low-level SDL sound functions. package audio // #cgo pkg-config: sdl -// #cgo darwin LDFLAGS: -lrt // #cgo freebsd LDFLAGS: -lrt // #cgo linux LDFLAGS: -lrt // #cgo windows LDFLAGS: -lpthread @@ -174,7 +173,6 @@ func UnlockAudio() { C.SDL_UnlockAudio() } - // Send samples to the audio device (AUDIO_S16SYS format). // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_int16(data []int16) { From bc756c563ca589c9e4d61071132cdb84b374d861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Tue, 8 May 2012 14:38:08 +0200 Subject: [PATCH 47/79] Better GOPATH handling in SDL test --- sdl-test/test.go | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/sdl-test/test.go b/sdl-test/test.go index 6fa9291..11dc9db 100644 --- a/sdl-test/test.go +++ b/sdl-test/test.go @@ -5,6 +5,7 @@ import ( "github.com/0xe2-0x9a-0x9b/Go-SDL/mixer" "github.com/0xe2-0x9a-0x9b/Go-SDL/sdl" "github.com/0xe2-0x9a-0x9b/Go-SDL/ttf" + "log" "math" "os" "strings" @@ -43,23 +44,34 @@ func worm(in <-chan Point, out chan<- Point, draw chan<- Point) { } func main() { + log.SetFlags(0) + var resourcePath string { - gopaths := os.Getenv("GOPATH") - if gopaths == "" { - panic("No such environment variable: GOPATH") + GOPATH := os.Getenv("GOPATH") + if GOPATH == "" { + log.Fatal("No such environment variable: GOPATH") + } + for _, gopath := range strings.Split(GOPATH, ":") { + a := gopath + "/src/github.com/0xe2-0x9a-0x9b/Go-SDL/sdl-test" + _, err := os.Stat(a) + if err == nil { + resourcePath = a + break + } + } + if resourcePath == "" { + log.Fatal("Failed to find resource directory") } - gopath := strings.Split(gopaths, ":")[0] - resourcePath = gopath + "/src/github.com/0xe2-0x9a-0x9b/Go-SDL/sdl-test" } var joy *sdl.Joystick if sdl.Init(sdl.INIT_EVERYTHING) != 0 { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } if ttf.Init() != 0 { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } if sdl.NumJoysticks() > 0 { @@ -79,13 +91,13 @@ func main() { if mixer.OpenAudio(mixer.DEFAULT_FREQUENCY, mixer.DEFAULT_FORMAT, mixer.DEFAULT_CHANNELS, 4096) != 0 { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } var screen = sdl.SetVideoMode(640, 480, 32, sdl.RESIZABLE) if screen == nil { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } var video_info = sdl.GetVideoInfo() @@ -101,7 +113,7 @@ func main() { image := sdl.Load(resourcePath + "/test.png") if image == nil { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } sdl.WM_SetIcon(image, nil) @@ -111,7 +123,7 @@ func main() { font := ttf.OpenFont(resourcePath+"/Fontin Sans.otf", 72) if font == nil { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } font.SetStyle(ttf.STYLE_UNDERLINE) @@ -120,13 +132,13 @@ func main() { music := mixer.LoadMUS(resourcePath + "/test.ogg") if music == nil { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } music.PlayMusic(-1) if sdl.GetKeyName(270) != "[+]" { - panic("GetKeyName broken") + log.Fatal("GetKeyName broken") } worm_in := make(chan Point) @@ -141,7 +153,7 @@ func main() { out = make(chan Point) go worm(in, out, draw) - ticker := time.NewTicker(1e9 / 50 /*50Hz*/ ) + ticker := time.NewTicker(time.Second / 50) // 50 Hz // Note: The following SDL code is highly ineffective. // It is eating too much CPU. If you intend to use Go-SDL, @@ -215,7 +227,7 @@ func main() { screen = sdl.SetVideoMode(int(e.W), int(e.H), 32, sdl.RESIZABLE) if screen == nil { - panic(sdl.GetError()) + log.Fatal(sdl.GetError()) } } } From fda02757407335185e1bd37403e04cdd06cf5103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 24 May 2012 19:26:32 +0200 Subject: [PATCH 48/79] Add more constants --- sdl/constants.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sdl/constants.go b/sdl/constants.go index e648b09..45e916c 100644 --- a/sdl/constants.go +++ b/sdl/constants.go @@ -16,6 +16,12 @@ const ( INIT_EVENTTHREAD = C.SDL_INIT_EVENTTHREAD INIT_EVERYTHING = C.SDL_INIT_EVERYTHING + // application states + + APPMOUSEFOCUS = C.SDL_APPMOUSEFOCUS + APPINPUTFOCUS = C.SDL_APPINPUTFOCUS + APPACTIVE = C.SDL_APPACTIVE + // setvideo flags SWSURFACE = C.SDL_SWSURFACE @@ -383,4 +389,29 @@ const ( HAT_RIGHTDOWN = C.SDL_HAT_RIGHTDOWN HAT_LEFTUP = C.SDL_HAT_LEFTUP HAT_LEFTDOWN = C.SDL_HAT_LEFTDOWN + + // keyboard/mouse state + + RELEASED = C.SDL_RELEASED + PRESSED = C.SDL_PRESSED + + // mouse button constants + + BUTTON_LEFT = C.SDL_BUTTON_LEFT + BUTTON_MIDDLE = C.SDL_BUTTON_MIDDLE + BUTTON_RIGHT = C.SDL_BUTTON_RIGHT + BUTTON_WHEELUP = C.SDL_BUTTON_WHEELUP + BUTTON_WHEELDOWN = C.SDL_BUTTON_WHEELDOWN + BUTTON_X1 = C.SDL_BUTTON_X1 + BUTTON_X2 = C.SDL_BUTTON_X2 + + // mouse button masks + + BUTTON_LMASK = 1 << (BUTTON_LEFT - 1) + BUTTON_MMASK = 1 << (BUTTON_MIDDLE - 1) + BUTTON_RMASK = 1 << (BUTTON_RIGHT - 1) + BUTTON_WHEELUPMASK = 1 << (BUTTON_WHEELUP - 1) + BUTTON_WHEELDOWNMASK = 1 << (BUTTON_WHEELDOWN - 1) + BUTTON_X1MASK = 1 << (BUTTON_X1 - 1) + BUTTON_X2MASK = 1 << (BUTTON_X2 - 1) ) From e4605f9fc41eb624d69a9d7e6e72e95b64e51e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 24 May 2012 20:15:14 +0200 Subject: [PATCH 49/79] darwin: use SDL_VIDEODRIVER=x11 --- sdl/sdl_darwin.go | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 sdl/sdl_darwin.go diff --git a/sdl/sdl_darwin.go b/sdl/sdl_darwin.go new file mode 100644 index 0000000..da434bb --- /dev/null +++ b/sdl/sdl_darwin.go @@ -0,0 +1,11 @@ +package sdl + +import ( + "os" +) + +func init() { + if os.Getenv("SDL_VIDEODRIVER") == "" { + os.Setenv("SDL_VIDEODRIVER", "x11") + } +} From f8ad2976960327c098b8e51adfb6ac6250546c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sat, 1 Sep 2012 12:18:31 +0200 Subject: [PATCH 50/79] Use runtime.LockOSThread() in sdl.GL_SwapBuffers() --- sdl/sdl.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdl/sdl.go b/sdl/sdl.go index 18f26fe..d20ffc0 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -366,13 +366,17 @@ func WM_ToggleFullScreen(surface *Surface) int { // Swaps OpenGL framebuffers/Update Display. func GL_SwapBuffers() { GlobalMutex.Lock() + runtime.LockOSThread() C.SDL_GL_SwapBuffers() + runtime.UnlockOSThread() GlobalMutex.Unlock() } func GL_SetAttribute(attr int, value int) int { GlobalMutex.Lock() + runtime.LockOSThread() status := int(C.SDL_GL_SetAttribute(C.SDL_GLattr(attr), C.int(value))) + runtime.UnlockOSThread() GlobalMutex.Unlock() return status } From 3d24e2ac6341fda63eba1d4eec0508e57ae9bb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sat, 1 Sep 2012 12:18:31 +0200 Subject: [PATCH 51/79] Use runtime.LockOSThread() in sdl.GL_SwapBuffers() --- sdl/sdl.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index 18f26fe..8d895ab 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -19,8 +19,12 @@ package sdl // static void SetError(const char* description){SDL_SetError("%s",description);} // static int __SDL_SaveBMP(SDL_Surface *surface, const char *file) { return SDL_SaveBMP(surface, file); } import "C" -import "unsafe" -import "sync" + +import ( + "runtime" + "sync" + "unsafe" +) type cast unsafe.Pointer @@ -366,13 +370,17 @@ func WM_ToggleFullScreen(surface *Surface) int { // Swaps OpenGL framebuffers/Update Display. func GL_SwapBuffers() { GlobalMutex.Lock() + runtime.LockOSThread() C.SDL_GL_SwapBuffers() + runtime.UnlockOSThread() GlobalMutex.Unlock() } func GL_SetAttribute(attr int, value int) int { GlobalMutex.Lock() + runtime.LockOSThread() status := int(C.SDL_GL_SetAttribute(C.SDL_GLattr(attr), C.int(value))) + runtime.UnlockOSThread() GlobalMutex.Unlock() return status } From be3a1ca9e7a9d09b95d8db0b15a049172357e411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Fri, 7 Sep 2012 13:43:09 +0200 Subject: [PATCH 52/79] Revert patch "Use runtime.LockOSThread() in sdl.GL_SwapBuffers()" --- sdl/sdl.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index 8d895ab..6e4d4fa 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -21,7 +21,6 @@ package sdl import "C" import ( - "runtime" "sync" "unsafe" ) @@ -370,17 +369,13 @@ func WM_ToggleFullScreen(surface *Surface) int { // Swaps OpenGL framebuffers/Update Display. func GL_SwapBuffers() { GlobalMutex.Lock() - runtime.LockOSThread() C.SDL_GL_SwapBuffers() - runtime.UnlockOSThread() GlobalMutex.Unlock() } func GL_SetAttribute(attr int, value int) int { GlobalMutex.Lock() - runtime.LockOSThread() status := int(C.SDL_GL_SetAttribute(C.SDL_GLattr(attr), C.int(value))) - runtime.UnlockOSThread() GlobalMutex.Unlock() return status } From e60f36699cfd30d81488990ccd710ff785b9c00d Mon Sep 17 00:00:00 2001 From: Caleb Spare Date: Mon, 10 Sep 2012 05:54:25 -0700 Subject: [PATCH 53/79] Add the DisplayFormatAlpha function. --- sdl/sdl.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sdl/sdl.go b/sdl/sdl.go index 6e4d4fa..dc406ac 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -556,6 +556,14 @@ func (s *Surface) DisplayFormat() *Surface { return wrap(p) } +// Converts a surface to the display format with alpha +func (s *Surface) DisplayFormatAlpha() *Surface { + s.mutex.RLock() + p := C.SDL_DisplayFormatAlpha(s.cSurface) + s.mutex.RUnlock() + return wrap(p) +} + // ======== // Keyboard // ======== From c6f47f29b996a5b59fb3cea5ebc044f650d9f0bc Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 18 Sep 2012 23:53:30 +0100 Subject: [PATCH 54/79] added linux/arm --- sdl/structs_arm.go | 171 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 sdl/structs_arm.go diff --git a/sdl/structs_arm.go b/sdl/structs_arm.go new file mode 100644 index 0000000..647e810 --- /dev/null +++ b/sdl/structs_arm.go @@ -0,0 +1,171 @@ +package sdl + +type PixelFormat struct { + Palette *Palette + BitsPerPixel uint8 + BytesPerPixel uint8 + Rloss uint8 + Gloss uint8 + Bloss uint8 + Aloss uint8 + Rshift uint8 + Gshift uint8 + Bshift uint8 + Ashift uint8 + Pad0 [2]byte + Rmask uint32 + Gmask uint32 + Bmask uint32 + Amask uint32 + Colorkey uint32 + Alpha uint8 + Pad1 [3]byte +} + +type Rect struct { + X int16 + Y int16 + W uint16 + H uint16 +} + +type Color struct { + R uint8 + G uint8 + B uint8 + Unused uint8 +} + +type Palette struct { + Ncolors int32 + Colors *Color +} + +type internalVideoInfo struct { + Flags uint32 + Video_mem uint32 + Vfmt *PixelFormat + Current_w int32 + Current_h int32 +} + +type Overlay struct { + Format uint32 + W int32 + H int32 + Planes int32 + Pitches *uint16 + Pixels **uint8 + Hwfuncs *[0]byte /* sprivate_yuvhwfuncs */ + Hwdata *[0]byte /* sprivate_yuvhwdata */ + Pad0 [4]byte +} + +type ActiveEvent struct { + Type uint8 + Gain uint8 + State uint8 +} + +type KeyboardEvent struct { + Type uint8 + Which uint8 + State uint8 + Pad0 [1]byte + Keysym Keysym +} + +type MouseMotionEvent struct { + Type uint8 + Which uint8 + State uint8 + Pad0 [1]byte + X uint16 + Y uint16 + Xrel int16 + Yrel int16 +} + +type MouseButtonEvent struct { + Type uint8 + Which uint8 + Button uint8 + State uint8 + X uint16 + Y uint16 +} + +type JoyAxisEvent struct { + Type uint8 + Which uint8 + Axis uint8 + Pad0 [1]byte + Value int16 +} + +type JoyBallEvent struct { + Type uint8 + Which uint8 + Ball uint8 + Pad0 [1]byte + Xrel int16 + Yrel int16 +} + +type JoyHatEvent struct { + Type uint8 + Which uint8 + Hat uint8 + Value uint8 +} + +type JoyButtonEvent struct { + Type uint8 + Which uint8 + Button uint8 + State uint8 +} + +type ResizeEvent struct { + Type uint8 + Pad0 [3]byte + W int32 + H int32 +} + +type ExposeEvent struct { + Type uint8 +} + +type QuitEvent struct { + Type uint8 +} + +type UserEvent struct { + Type uint8 + Pad0 [3]byte + Code int32 + Data1 *byte + Data2 *byte +} + +type SysWMmsg struct{} + +type SysWMEvent struct { + Type uint8 + Pad0 [3]byte + Msg *SysWMmsg +} + +type Event struct { + Type uint8 + Pad0 [19]byte +} + +type Keysym struct { + Scancode uint8 + Pad0 [3]byte + Sym uint32 + Mod uint32 + Unicode uint16 +} From 9616c796cf0969198fa90538a0f7b963a241aa93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sun, 25 Nov 2012 09:15:09 +0100 Subject: [PATCH 55/79] Do not force SDL_VIDEODRIVER=x11 on Darwin --- sdl/sdl.go | 20 ++++++++++++++++++++ sdl/sdl_darwin.go | 6 +++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index dc406ac..1a5a46c 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -21,6 +21,8 @@ package sdl import "C" import ( + "os" + "runtime" "sync" "unsafe" ) @@ -108,6 +110,15 @@ func GoSdlVersion() string { func Init(flags uint32) int { GlobalMutex.Lock() status := int(C.SDL_Init(C.Uint32(flags))) + if (status != 0) && (runtime.GOOS == "darwin") && (flags&INIT_VIDEO != 0) { + if os.Getenv("SDL_VIDEODRIVER") == "" { + os.Setenv("SDL_VIDEODRIVER", "x11") + status = int(C.SDL_Init(C.Uint32(flags))) + if status != 0 { + os.Setenv("SDL_VIDEODRIVER", "") + } + } + } GlobalMutex.Unlock() return status } @@ -130,6 +141,15 @@ func Quit() { func InitSubSystem(flags uint32) int { GlobalMutex.Lock() status := int(C.SDL_InitSubSystem(C.Uint32(flags))) + if (status != 0) && (runtime.GOOS == "darwin") && (flags&INIT_VIDEO != 0) { + if os.Getenv("SDL_VIDEODRIVER") == "" { + os.Setenv("SDL_VIDEODRIVER", "x11") + status = int(C.SDL_InitSubSystem(C.Uint32(flags))) + if status != 0 { + os.Setenv("SDL_VIDEODRIVER", "") + } + } + } GlobalMutex.Unlock() return status } diff --git a/sdl/sdl_darwin.go b/sdl/sdl_darwin.go index da434bb..711d30e 100644 --- a/sdl/sdl_darwin.go +++ b/sdl/sdl_darwin.go @@ -5,7 +5,7 @@ import ( ) func init() { - if os.Getenv("SDL_VIDEODRIVER") == "" { - os.Setenv("SDL_VIDEODRIVER", "x11") - } + //if os.Getenv("SDL_VIDEODRIVER") == "" { + // os.Setenv("SDL_VIDEODRIVER", "x11") + //} } From 7180e26b4259f5250dbbc66f77c65795b441cdb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Neves?= Date: Sun, 23 Dec 2012 18:18:22 +0000 Subject: [PATCH 56/79] Comment out unused "os" import --- sdl/sdl_darwin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdl/sdl_darwin.go b/sdl/sdl_darwin.go index 711d30e..50ce7da 100644 --- a/sdl/sdl_darwin.go +++ b/sdl/sdl_darwin.go @@ -1,7 +1,7 @@ package sdl import ( - "os" + //"os" ) func init() { From 476ec31b92aa632c3c6fad96dd42d5628edf7c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 17 Jan 2013 13:17:13 +0100 Subject: [PATCH 57/79] Fix cgo include paths --- mixer/mixer.go | 2 +- sdl/audio/audio.go | 2 +- sdl/audio/callback.h | 2 +- sdl/constants.go | 2 +- sdl/sdl.go | 4 ++-- ttf/ttf.go | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mixer/mixer.go b/mixer/mixer.go index c0bdb8a..db6456e 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -9,7 +9,7 @@ package mixer // #cgo pkg-config: sdl // #cgo LDFLAGS: -lSDL_mixer -// #include +// #include import "C" import "unsafe" diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 4f0f9ea..8a096f5 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -14,7 +14,7 @@ package audio // #cgo freebsd LDFLAGS: -lrt // #cgo linux LDFLAGS: -lrt // #cgo windows LDFLAGS: -lpthread -// #include +// #include // #include "callback.h" import "C" import "unsafe" diff --git a/sdl/audio/callback.h b/sdl/audio/callback.h index fdde71b..8e181ae 100644 --- a/sdl/audio/callback.h +++ b/sdl/audio/callback.h @@ -5,7 +5,7 @@ * except for usages in immoral contexts. */ -#include +#include typedef void (SDLCALL *callback_t)(void *userdata, Uint8 *stream, int len); diff --git a/sdl/constants.go b/sdl/constants.go index 45e916c..c1031b8 100644 --- a/sdl/constants.go +++ b/sdl/constants.go @@ -1,7 +1,7 @@ package sdl // #cgo pkg-config: sdl -// #include +// #include import "C" const ( diff --git a/sdl/sdl.go b/sdl/sdl.go index 1a5a46c..d8146e2 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -14,8 +14,8 @@ package sdl // struct SDL_BlitMap{}; // #define map _map // -// #include -// #include +// #include +// #include // static void SetError(const char* description){SDL_SetError("%s",description);} // static int __SDL_SaveBMP(SDL_Surface *surface, const char *file) { return SDL_SaveBMP(surface, file); } import "C" diff --git a/ttf/ttf.go b/ttf/ttf.go index bc9ded9..7415ddc 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -9,7 +9,7 @@ package ttf // #cgo pkg-config: sdl // #cgo LDFLAGS: -lSDL_ttf -// #include +// #include import "C" import ( From cf243dd174900ccbdf1b6c336b4e1361c17cf052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Thu, 17 Jan 2013 15:01:47 +0100 Subject: [PATCH 58/79] Update cgo pkg-config directives --- mixer/mixer.go | 3 +-- sdl/sdl.go | 3 +-- ttf/ttf.go | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/mixer/mixer.go b/mixer/mixer.go index db6456e..9b71ba4 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -7,8 +7,7 @@ functions have been changed to be in a more object-oriented style */ package mixer -// #cgo pkg-config: sdl -// #cgo LDFLAGS: -lSDL_mixer +// #cgo pkg-config: SDL_mixer // #include import "C" import "unsafe" diff --git a/sdl/sdl.go b/sdl/sdl.go index d8146e2..187121a 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -7,8 +7,7 @@ flavor (eg. Rather than sdl.Flip(surface) it's surface.Flip() ) */ package sdl -// #cgo pkg-config: sdl -// #cgo LDFLAGS: -lSDL_image +// #cgo pkg-config: sdl SDL_image // // struct private_hwdata{}; // struct SDL_BlitMap{}; diff --git a/ttf/ttf.go b/ttf/ttf.go index 7415ddc..7f036d8 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -7,8 +7,7 @@ that work with loaded fonts are changed to have a more object-oriented feel. */ package ttf -// #cgo pkg-config: sdl -// #cgo LDFLAGS: -lSDL_ttf +// #cgo pkg-config: SDL_ttf // #include import "C" From a005db5c93c5b3474a5a2059b78a7d2e4451fc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 30 Jan 2013 16:40:27 +0100 Subject: [PATCH 59/79] Add sdl.Delay function --- sdl/sdl.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sdl/sdl.go b/sdl/sdl.go index 187121a..317a478 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -23,6 +23,7 @@ import ( "os" "runtime" "sync" + "time" "unsafe" ) @@ -846,3 +847,12 @@ func (joystick *Joystick) GetBall(ball int, dx, dy *int) int { func (joystick *Joystick) GetAxis(axis int) int16 { return int16(C.SDL_JoystickGetAxis(joystick.cJoystick, C.int(axis))) } + +// ======== +// Time +// ======== + +// Waits a specified number of milliseconds before returning. +func Delay(ms uint32) { + time.Sleep(time.Duration(ms) * time.Millisecond) +} From 5b0bca949d3a2d1d65e54721a5ad482e3f4fa677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Wed, 30 Jan 2013 17:36:41 +0100 Subject: [PATCH 60/79] Add sdl.GetTicks function --- sdl/sdl.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index 317a478..9b718bb 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -119,6 +119,7 @@ func Init(flags uint32) int { } } } + GlobalMutex.Unlock() return status } @@ -848,9 +849,17 @@ func (joystick *Joystick) GetAxis(axis int) int16 { return int16(C.SDL_JoystickGetAxis(joystick.cJoystick, C.int(axis))) } -// ======== +// ==== // Time -// ======== +// ==== + +// Gets the number of milliseconds since the SDL library initialization. +func GetTicks() uint32 { + GlobalMutex.Lock() + t := uint32(C.SDL_GetTicks()) + GlobalMutex.Unlock() + return t +} // Waits a specified number of milliseconds before returning. func Delay(ms uint32) { From 5cb687c9c1da6a3381ca01bc7a7907dc0d119311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9A=9B?= <0xe2.0x9a.0x9b@gmail.com> Date: Sat, 2 Feb 2013 13:10:35 +0100 Subject: [PATCH 61/79] Add sdl.CreateRGBSurfaceFrom --- sdl/sdl.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/sdl/sdl.go b/sdl/sdl.go index 9b718bb..9596004 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -21,6 +21,7 @@ import "C" import ( "os" + "reflect" "runtime" "sync" "time" @@ -50,6 +51,8 @@ type Surface struct { Pitch uint16 Pixels unsafe.Pointer Offset int32 + + gcPixels interface{} // Prevents garbage collection of pixels passed to func CreateRGBSurfaceFrom } func wrap(cSurface *C.SDL_Surface) *Surface { @@ -88,6 +91,7 @@ func (s *Surface) destroy() { s.cSurface = nil s.Format = nil s.Pixels = nil + s.gcPixels = nil } // ======= @@ -569,6 +573,26 @@ func CreateRGBSurface(flags uint32, width int, height int, bpp int, Rmask uint32 return wrap(p) } +// Creates a Surface from existing pixel data. It expects pixels to be a slice, pointer or unsafe.Pointer. +func CreateRGBSurfaceFrom(pixels interface{}, width, height, bpp, pitch int, Rmask, Gmask, Bmask, Amask uint32) *Surface { + var ptr unsafe.Pointer + switch v := reflect.ValueOf(pixels); v.Kind() { + case reflect.Ptr, reflect.UnsafePointer, reflect.Slice: + ptr = unsafe.Pointer(v.Pointer()) + default: + panic("Don't know how to handle type: " + v.Kind().String()) + } + + GlobalMutex.Lock() + p := C.SDL_CreateRGBSurfaceFrom(ptr, C.int(width), C.int(height), C.int(bpp), C.int(pitch), + C.Uint32(Rmask), C.Uint32(Gmask), C.Uint32(Bmask), C.Uint32(Amask)) + GlobalMutex.Unlock() + + s := wrap(p) + s.gcPixels = pixels + return s +} + // Converts a surface to the display format func (s *Surface) DisplayFormat() *Surface { s.mutex.RLock() From 88d907c020c686c9eb32498b79b1564886c982df Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 20:30:59 +0100 Subject: [PATCH 62/79] introducing callback-based sound mixing --- sdl/audio/audio.go | 261 +++++++++++++++++++++++++------------- sdl/audio/callback.c | 170 ++----------------------- sdl/audio/callback.c.orig | 181 ++++++++++++++++++++++++++ sdl/audio/callback.h | 18 ++- 4 files changed, 379 insertions(+), 251 deletions(-) create mode 100644 sdl/audio/callback.c.orig diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 8a096f5..a5c0a4b 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -1,12 +1,16 @@ /* + * Copyright neagix - Feb 2013 * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 + * * * The contents of this file can be used freely, * except for usages in immoral contexts. + * */ /* -An interface to low-level SDL sound functions. +An interface to low-level SDL sound functions +with support for callbacks and rudimentary stream mixing */ package audio @@ -18,7 +22,8 @@ package audio // #include "callback.h" import "C" import "unsafe" -import "sync" +import "reflect" +import "code.google.com/p/rog-go/exp/callback" // The version of Go-SDL audio bindings. // The version descriptor changes into a new unique string @@ -29,7 +34,18 @@ import "sync" // // If Go adds some kind of support for package versioning, this function will go away. func GoSdlAudioVersion() string { - return "⚛SDL audio bindings 1.0" + return "Go-SDL audio 1.1" +} + +var userDefinedCallback func(unsafe.Pointer, int) + +//export streamCallback +func streamCallback(arg unsafe.Pointer) { + ctx := (*C.context)(arg) + + // call the actual Go callback defined by user + //NOTE: here buffer truncation possible with large NumBytes + userDefinedCallback(ctx.Stream, int(ctx.NumBytes)) } // Audio format @@ -57,9 +73,141 @@ type AudioSpec struct { Out_Silence uint8 Samples uint16 // A power of 2, preferrably 2^11 (2048) or more Out_Size uint32 + UserDefinedCallback func(unsafe.Pointer, int) +} + +var alreadyOpened bool + +const ( + // play concatenating samples + AE_PLAY_CONCAT = iota + //TODO: downmix mode + AE_PAUSE + AE_UNPAUSE +) + +type AudioEvent struct { + Event int + Buffer []int16 +} + +// Audio status +const ( + SDL_AUDIO_STOPPED = C.SDL_AUDIO_STOPPED + SDL_AUDIO_PLAYING = C.SDL_AUDIO_PLAYING + SDL_AUDIO_PAUSED = C.SDL_AUDIO_PAUSED +) + +var PlayLoop chan AudioEvent +var PlayQueueSize int +var TailBuffer []int16 + +//NOTE: we assume this is not going to be called concurrently :) +func DownstreamPlayback16(buffer unsafe.Pointer, bufferSize int) { + + // hack to convert C void* pointer to proper Go slice + var stream []int16 + streamLen := bufferSize / 2 + tailBufferLen := len(TailBuffer) + sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&stream))) + sliceHeader.Cap = streamLen + sliceHeader.Len = streamLen + sliceHeader.Data = uintptr(buffer) + + // in theory we should overmix samples, but for that a double-buffered approach is best + // right now we will just concatenate samples, quirky but serves the purpose of this game + + // first thing, pick any eventual remnants buffer to copy over + dstOffset := 0 + if nil != TailBuffer && tailBufferLen > 0 { + for i := range TailBuffer { + stream[dstOffset] = TailBuffer[i] + dstOffset++ + + // we have copied enough + if dstOffset == streamLen { + newTailBuffer := make([]int16, tailBufferLen-dstOffset) + copy(newTailBuffer, TailBuffer[dstOffset:]) + TailBuffer = newTailBuffer + return + } + } + + // we have consumed the whole TailBuffer, reset it + TailBuffer = nil + } + + // pick next beep object + for { + // if there's nothing in queue, just play what we got so far + // by default stream is a silence buffer + if 0 == PlayQueueSize { + return + } + + ae := <-PlayLoop + + switch ae.Event { + case AE_UNPAUSE: + { + PauseAudio(false) + continue + } + case AE_PAUSE: + { + PauseAudio(true) + continue + } + } + + // prepare eventual tail buffer + toBeCopied := streamLen - dstOffset + overflowingSamples := len(ae.Buffer) - toBeCopied + if overflowingSamples > 0 { + TailBuffer = make([]int16, overflowingSamples) + } + + copy(stream[dstOffset:], ae.Buffer) + if overflowingSamples > 0 { + copy(TailBuffer, ae.Buffer[toBeCopied:]) + } + + + // we have "eaten" a sound object from the queue + PlayQueueSize-- + + + // this sound object fully satisfied the buffer + if overflowingSamples > 0 { + return } + + // in case of perfect boundary match + if streamLen == dstOffset + toBeCopied { + return } + + // loop again, pick another sound + } } func OpenAudio(desired, obtained_orNil *AudioSpec) int { + if alreadyOpened { + panic("more than 1 audio stream currently not supported") + } + + C.setCallbackFunc(callback.Func) + // copy handle to user-defined callback function, if defined + // it is perfectly supported to not specify the callback function + // in that case you will use default SendAudio semantics + // note that if you specify a callback and use SendAudio, a hangup will instead happen + // when calling SendAudio + + if nil != desired.UserDefinedCallback { + userDefinedCallback = desired.UserDefinedCallback + } else { + userDefinedCallback = DownstreamPlayback16 + PlayLoop = make(chan AudioEvent) + } + var C_desired, C_obtained *C.SDL_AudioSpec C_desired = new(C.SDL_AudioSpec) @@ -80,9 +228,7 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { status := C.SDL_OpenAudio(C_desired, C_obtained) if status == 0 { - mutex.Lock() - opened++ - mutex.Unlock() + alreadyOpened = true } if obtained_orNil != nil { @@ -100,129 +246,62 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { } func CloseAudio() { - PauseAudio(true) - - mutex.Lock() - { - opened-- - switch { - case opened == 0: - userPaused = true - sdlPaused = true - case opened < 0: + if !alreadyOpened { panic("SDL audio not opened") } - } - mutex.Unlock() - C.callback_unblock() + PauseAudio(true) C.SDL_CloseAudio() } -// Audio status -const ( - SDL_AUDIO_STOPPED = C.SDL_AUDIO_STOPPED - SDL_AUDIO_PLAYING = C.SDL_AUDIO_PLAYING - SDL_AUDIO_PAUSED = C.SDL_AUDIO_PAUSED -) - func GetAudioStatus() int { return int(C.SDL_GetAudioStatus()) } -var opened int = 0 - -var userPaused bool = true -var sdlPaused bool = true -var haveData bool = false - -var mutex sync.Mutex - // Pause or unpause the audio. -// Unpausing is deferred until a SendAudio function receives some samples. func PauseAudio(pause_on bool) { - mutex.Lock() - - if pause_on != sdlPaused { if pause_on { - // Pause SDL audio - userPaused = true - sdlPaused = true C.SDL_PauseAudio(1) } else { - userPaused = false - if haveData { - // Unpause SDL audio - sdlPaused = false - C.SDL_PauseAudio(0) - } else { - // Defer until SendAudio is called - } + C.SDL_PauseAudio(0) } - } - - mutex.Unlock() } -func LockAudio() { - C.SDL_LockAudio() +// pause or unpause the audio synchronously +func PauseAudioSync(pause_on bool) { + if nil == PlayLoop { + panic("Cannot use PauseAudioSync with custom callback") + } + if pause_on { + PlayLoop <- AudioEvent{Event:AE_PAUSE} + } else { + PlayLoop <- AudioEvent{Event:AE_UNPAUSE} + } } -func UnlockAudio() { - C.SDL_UnlockAudio() -} // Send samples to the audio device (AUDIO_S16SYS format). // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_int16(data []int16) { - if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) - } + PlayQueueSize++ + PlayLoop <- AudioEvent{Event:AE_PLAY_CONCAT, Buffer: data} } // Send samples to the audio device (AUDIO_U16SYS format). // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_uint16(data []uint16) { - if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) - } + panic("Only int16 samples currently supported") } // Send samples to the audio device (AUDIO_S8 format). // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_int8(data []int8) { - if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) - } + panic("Only int16 samples currently supported") } // Send samples to the audio device (AUDIO_U8 format). // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_uint8(data []uint8) { - if len(data) > 0 { - sendAudio((*C.Uint8)(unsafe.Pointer(&data[0])), C.size_t(int(unsafe.Sizeof(data[0]))*len(data))) - } -} - -func sendAudio(data *C.Uint8, numBytes C.size_t) { - if numBytes > 0 { - mutex.Lock() - { - haveData = true - - if (userPaused == false) && (sdlPaused == true) { - // Unpause SDL audio - sdlPaused = false - C.SDL_PauseAudio(0) - } - } - mutex.Unlock() - - C.callback_fillBuffer(data, numBytes) - - mutex.Lock() - haveData = false - mutex.Unlock() - } + panic("Only int16 samples currently supported") } diff --git a/sdl/audio/callback.c b/sdl/audio/callback.c index 1ac0531..ae824fb 100644 --- a/sdl/audio/callback.c +++ b/sdl/audio/callback.c @@ -8,172 +8,26 @@ #include "callback.h" #include #include -#include #include +#include "_cgo_export.h" -#define TRUE 1 -#define FALSE 0 +// callbackFunc holds the callback library function. +// It is stored in a function pointer because C linkage +// does not work across packages. +static void(*callbackFunc)(void (*f)(void*), void*); -// Uncomment the next line to enable debugging messages -//#define DEBUG +void setCallbackFunc(void *cb){ callbackFunc = cb; } -static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t need = PTHREAD_COND_INITIALIZER; -static pthread_cond_t avail = PTHREAD_COND_INITIALIZER; -static size_t needed = 0; // Number of bytes needed by the consumer -static size_t available = 0; // Number of bytes available (from the producer) +static void SDLCALL callback(void *userdata, Uint8 *_stream, int len) { -static Uint8 *stream; // Communication buffer between the consumer and the producer + SDL_LockAudio(); -#ifdef DEBUG -#include -static int64_t get_time() { - struct timespec ts; - if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) - return 1000000000*(int64_t)ts.tv_sec + (int64_t)ts.tv_nsec; - else - return -1; -} -#endif - -#ifdef DEBUG -static uint64_t cummulativeLatency = 0; -static unsigned numCallbacks = 0; -#endif - -static void SDLCALL callback(void *userdata, Uint8 *_stream, int _len) { - assert(_len > 0); - - size_t len = (size_t)_len; - - pthread_mutex_lock(&m); - { - assert(available == 0); - stream = _stream; - - { - #ifdef DEBUG - int64_t t1 = get_time(); - printf("consumer: t1=%lld µs\n", (long long)t1/1000); - #endif - - assert(needed == 0); - #ifdef DEBUG - printf("consumer: needed <- %zu\n", len); - #endif - needed = len; - pthread_cond_signal(&need); - - #ifdef DEBUG - printf("consumer: waiting for data\n"); - #endif - pthread_cond_wait(&avail, &m); - assert(needed == 0); - assert(available == len); - - #ifdef DEBUG - int64_t t2 = get_time(); - printf("consumer: t2=%lld µs\n", (long long)t2/1000); - if(t1>0 && t2>0) { - uint64_t latency = t2-t1; - cummulativeLatency += latency; - numCallbacks++; - printf("consumer: latency=%lld µs, avg=%u µs\n", - (long long)(latency/1000), - (unsigned)(cummulativeLatency/numCallbacks/1000)); - } - #endif - } - - #ifdef DEBUG - printf("consumer: received %zu bytes of data\n", available); - printf("consumer: available <- 0\n"); - #endif - available = 0; - stream = NULL; - } - pthread_mutex_unlock(&m); + context context = { _stream, len }; + callbackFunc(streamCallback, &context); + + SDL_UnlockAudio(); } callback_t callback_getCallback() { return &callback; } - -void callback_fillBuffer(Uint8 *data, size_t numBytes) { - size_t sent = 0; - - pthread_mutex_lock(&m); - - while(sent < numBytes) { - #ifdef DEBUG - int64_t t = get_time(); - printf("producer: t=%lld µs\n", (long long)t/1000); - #endif - - if(needed == 0) { - #ifdef DEBUG - printf("producer: waiting until data is needed (1)\n"); - #endif - pthread_cond_wait(&need, &m); - - // Interrupted from 'callback_unblock' ? - if(needed == 0) { - #ifdef DEBUG - printf("producer: interrupted (1)\n"); - #endif - break; - } - } - - assert(stream != NULL); - assert(needed > 0); - - // Append a chunk of data to the 'stream' - size_t n = (needed<(numBytes-sent)) ? needed : (numBytes-sent); - memcpy(stream+available, data+sent, n); - available += n; - sent += n; - needed -= n; - - #ifdef DEBUG - printf("producer: added %zu bytes, available=%zu\n", n, available); - #endif - - if(needed == 0) { - pthread_cond_signal(&avail); - if(sent < numBytes) { - #ifdef DEBUG - printf("producer: waiting until data is needed (2)\n"); - #endif - pthread_cond_wait(&need, &m); - - // Interrupted from 'callback_unblock' ? - if(needed == 0) { - #ifdef DEBUG - printf("producer: interrupted (2)\n"); - #endif - break; - } - } - else { - break; - } - } - } - - pthread_mutex_unlock(&m); -} - -void callback_unblock() { - pthread_mutex_lock(&m); - if(needed > 0) { - // Note: SDL already prefilled the entire 'stream' with silence - assert(stream != NULL); - available += needed; - needed = 0; - pthread_cond_signal(&avail); - } - pthread_cond_signal(&need); - pthread_mutex_unlock(&m); -} - diff --git a/sdl/audio/callback.c.orig b/sdl/audio/callback.c.orig new file mode 100644 index 0000000..2f71695 --- /dev/null +++ b/sdl/audio/callback.c.orig @@ -0,0 +1,181 @@ +/* + * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 + * + * The contents of this file can be used freely, + * except for usages in immoral contexts. + */ + +#include "callback.h" +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +// Uncomment the next line to enable debugging messages +//#define DEBUG + +static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t need = PTHREAD_COND_INITIALIZER; +static pthread_cond_t avail = PTHREAD_COND_INITIALIZER; +static size_t needed = 0; // Number of bytes needed by the consumer +static size_t available = 0; // Number of bytes available (from the producer) + +static Uint8 *stream; // Communication buffer between the consumer and the producer + +#ifdef DEBUG +#include +static int64_t get_time() { + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + return 1000000000*(int64_t)ts.tv_sec + (int64_t)ts.tv_nsec; + else + return -1; +} +#endif + +#ifdef DEBUG +static uint64_t cummulativeLatency = 0; +static unsigned numCallbacks = 0; +#endif + +static void SDLCALL callback(void *userdata, Uint8 *_stream, int _len) { + assert(_len > 0); + + size_t len = (size_t)_len; + +// SDL_LockAudio(); + pthread_mutex_lock(&m); + { + assert(available == 0); + stream = _stream; + + { + #ifdef DEBUG + int64_t t1 = get_time(); + printf("consumer: t1=%lld µs\n", (long long)t1/1000); + #endif + + assert(needed == 0); + #ifdef DEBUG + printf("consumer: needed <- %zu\n", len); + #endif + needed = len; + pthread_cond_signal(&need); + + #ifdef DEBUG + printf("consumer: waiting for data\n"); + #endif + pthread_cond_wait(&avail, &m); + assert(needed == 0); + assert(available == len); + + #ifdef DEBUG + int64_t t2 = get_time(); + printf("consumer: t2=%lld µs\n", (long long)t2/1000); + if(t1>0 && t2>0) { + uint64_t latency = t2-t1; + cummulativeLatency += latency; + numCallbacks++; + printf("consumer: latency=%lld µs, avg=%u µs\n", + (long long)(latency/1000), + (unsigned)(cummulativeLatency/numCallbacks/1000)); + } + #endif + } + + #ifdef DEBUG + printf("consumer: received %zu bytes of data\n", available); + printf("consumer: available <- 0\n"); + #endif + available = 0; + stream = NULL; + } + pthread_mutex_unlock(&m); +// SDL_UnlockAudio(); +} + +callback_t callback_getCallback() { + return &callback; +} + +void callback_fillBuffer(Uint8 *data, size_t numBytes) { + size_t sent = 0; + + pthread_mutex_lock(&m); + + while(sent < numBytes) { + #ifdef DEBUG + int64_t t = get_time(); + printf("producer: t=%lld µs\n", (long long)t/1000); + #endif + + if(needed == 0) { + #ifdef DEBUG + printf("producer: waiting until data is needed (1)\n"); + #endif + pthread_cond_wait(&need, &m); + + // Interrupted from 'callback_unblock' ? + if(needed == 0) { + #ifdef DEBUG + printf("producer: interrupted (1)\n"); + #endif + break; + } + } + + assert(stream != NULL); + assert(needed > 0); + + // Append a chunk of data to the 'stream' + size_t n = (needed<(numBytes-sent)) ? needed : (numBytes-sent); + memcpy(stream+available, data+sent, n); + available += n; + sent += n; + needed -= n; + + #ifdef DEBUG + printf("producer: added %zu bytes, available=%zu\n", n, available); + #endif + + if(needed == 0) { + pthread_cond_signal(&avail); + if(sent < numBytes) { + #ifdef DEBUG + printf("producer: waiting until data is needed (2)\n"); + #endif + pthread_cond_wait(&need, &m); + + // Interrupted from 'callback_unblock' ? + if(needed == 0) { + #ifdef DEBUG + printf("producer: interrupted (2)\n"); + #endif + break; + } + } + else { + break; + } + } + } + + pthread_mutex_unlock(&m); +} + +void callback_unblock() { + pthread_mutex_lock(&m); + if(needed > 0) { + // Note: SDL already prefilled the entire 'stream' with silence + assert(stream != NULL); + available += needed; + needed = 0; + pthread_cond_signal(&avail); + } + pthread_cond_signal(&need); + pthread_mutex_unlock(&m); +} + diff --git a/sdl/audio/callback.h b/sdl/audio/callback.h index 8e181ae..5ac0a81 100644 --- a/sdl/audio/callback.h +++ b/sdl/audio/callback.h @@ -4,12 +4,26 @@ * The contents of this file can be used freely, * except for usages in immoral contexts. */ + +#ifndef __CALLBACK_H +#define __CALLBACK_H #include +typedef struct context context; +struct context { + void *Stream; + int NumBytes; +}; + typedef void (SDLCALL *callback_t)(void *userdata, Uint8 *stream, int len); extern callback_t callback_getCallback(); -extern void callback_fillBuffer(Uint8 *data, size_t numBytes); -extern void callback_unblock(); +//extern void callback_fillBuffer(Uint8 *data, size_t numBytes); +//extern void callback_unblock(); + +// from pa.c +extern void setCallbackFunc(void *cb); +extern int paStreamCallback(void *outputBuffer, unsigned long bytesCount); +#endif //__CALLBACK_H From 9926446d382e66146d9bc279c4f133bbef2f781c Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 20:31:51 +0100 Subject: [PATCH 63/79] formatting & remove old version of callback.c --- sdl/audio/audio.go | 99 +++++++++++---------- sdl/audio/callback.c.orig | 181 -------------------------------------- 2 files changed, 49 insertions(+), 231 deletions(-) delete mode 100644 sdl/audio/callback.c.orig diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index a5c0a4b..2471178 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -42,7 +42,7 @@ var userDefinedCallback func(unsafe.Pointer, int) //export streamCallback func streamCallback(arg unsafe.Pointer) { ctx := (*C.context)(arg) - + // call the actual Go callback defined by user //NOTE: here buffer truncation possible with large NumBytes userDefinedCallback(ctx.Stream, int(ctx.NumBytes)) @@ -67,16 +67,16 @@ const ( ) type AudioSpec struct { - Freq int - Format uint16 // If in doubt, use AUDIO_S16SYS - Channels uint8 // 1 or 2 - Out_Silence uint8 - Samples uint16 // A power of 2, preferrably 2^11 (2048) or more - Out_Size uint32 + Freq int + Format uint16 // If in doubt, use AUDIO_S16SYS + Channels uint8 // 1 or 2 + Out_Silence uint8 + Samples uint16 // A power of 2, preferrably 2^11 (2048) or more + Out_Size uint32 UserDefinedCallback func(unsafe.Pointer, int) } -var alreadyOpened bool +var alreadyOpened bool const ( // play concatenating samples @@ -87,8 +87,8 @@ const ( ) type AudioEvent struct { - Event int - Buffer []int16 + Event int + Buffer []int16 } // Audio status @@ -98,7 +98,7 @@ const ( SDL_AUDIO_PAUSED = C.SDL_AUDIO_PAUSED ) -var PlayLoop chan AudioEvent +var PlayLoop chan AudioEvent var PlayQueueSize int var TailBuffer []int16 @@ -146,18 +146,18 @@ func DownstreamPlayback16(buffer unsafe.Pointer, bufferSize int) { } ae := <-PlayLoop - + switch ae.Event { - case AE_UNPAUSE: - { - PauseAudio(false) - continue + case AE_UNPAUSE: + { + PauseAudio(false) + continue + } + case AE_PAUSE: + { + PauseAudio(true) + continue } - case AE_PAUSE: - { - PauseAudio(true) - continue - } } // prepare eventual tail buffer @@ -171,28 +171,28 @@ func DownstreamPlayback16(buffer unsafe.Pointer, bufferSize int) { if overflowingSamples > 0 { copy(TailBuffer, ae.Buffer[toBeCopied:]) } - - + // we have "eaten" a sound object from the queue PlayQueueSize-- - - + // this sound object fully satisfied the buffer if overflowingSamples > 0 { - return } - + return + } + // in case of perfect boundary match - if streamLen == dstOffset + toBeCopied { - return } - + if streamLen == dstOffset+toBeCopied { + return + } + // loop again, pick another sound } } func OpenAudio(desired, obtained_orNil *AudioSpec) int { - if alreadyOpened { - panic("more than 1 audio stream currently not supported") - } + if alreadyOpened { + panic("more than 1 audio stream currently not supported") + } C.setCallbackFunc(callback.Func) // copy handle to user-defined callback function, if defined @@ -200,14 +200,14 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { // in that case you will use default SendAudio semantics // note that if you specify a callback and use SendAudio, a hangup will instead happen // when calling SendAudio - + if nil != desired.UserDefinedCallback { userDefinedCallback = desired.UserDefinedCallback } else { userDefinedCallback = DownstreamPlayback16 PlayLoop = make(chan AudioEvent) } - + var C_desired, C_obtained *C.SDL_AudioSpec C_desired = new(C.SDL_AudioSpec) @@ -246,9 +246,9 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { } func CloseAudio() { - if !alreadyOpened { - panic("SDL audio not opened") - } + if !alreadyOpened { + panic("SDL audio not opened") + } PauseAudio(true) @@ -261,11 +261,11 @@ func GetAudioStatus() int { // Pause or unpause the audio. func PauseAudio(pause_on bool) { - if pause_on { - C.SDL_PauseAudio(1) - } else { - C.SDL_PauseAudio(0) - } + if pause_on { + C.SDL_PauseAudio(1) + } else { + C.SDL_PauseAudio(0) + } } // pause or unpause the audio synchronously @@ -273,19 +273,18 @@ func PauseAudioSync(pause_on bool) { if nil == PlayLoop { panic("Cannot use PauseAudioSync with custom callback") } - if pause_on { - PlayLoop <- AudioEvent{Event:AE_PAUSE} - } else { - PlayLoop <- AudioEvent{Event:AE_UNPAUSE} - } + if pause_on { + PlayLoop <- AudioEvent{Event: AE_PAUSE} + } else { + PlayLoop <- AudioEvent{Event: AE_UNPAUSE} + } } - // Send samples to the audio device (AUDIO_S16SYS format). // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_int16(data []int16) { PlayQueueSize++ - PlayLoop <- AudioEvent{Event:AE_PLAY_CONCAT, Buffer: data} + PlayLoop <- AudioEvent{Event: AE_PLAY_CONCAT, Buffer: data} } // Send samples to the audio device (AUDIO_U16SYS format). diff --git a/sdl/audio/callback.c.orig b/sdl/audio/callback.c.orig deleted file mode 100644 index 2f71695..0000000 --- a/sdl/audio/callback.c.orig +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 - * - * The contents of this file can be used freely, - * except for usages in immoral contexts. - */ - -#include "callback.h" -#include -#include -#include -#include - -#define TRUE 1 -#define FALSE 0 - -// Uncomment the next line to enable debugging messages -//#define DEBUG - -static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t need = PTHREAD_COND_INITIALIZER; -static pthread_cond_t avail = PTHREAD_COND_INITIALIZER; -static size_t needed = 0; // Number of bytes needed by the consumer -static size_t available = 0; // Number of bytes available (from the producer) - -static Uint8 *stream; // Communication buffer between the consumer and the producer - -#ifdef DEBUG -#include -static int64_t get_time() { - struct timespec ts; - if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) - return 1000000000*(int64_t)ts.tv_sec + (int64_t)ts.tv_nsec; - else - return -1; -} -#endif - -#ifdef DEBUG -static uint64_t cummulativeLatency = 0; -static unsigned numCallbacks = 0; -#endif - -static void SDLCALL callback(void *userdata, Uint8 *_stream, int _len) { - assert(_len > 0); - - size_t len = (size_t)_len; - -// SDL_LockAudio(); - pthread_mutex_lock(&m); - { - assert(available == 0); - stream = _stream; - - { - #ifdef DEBUG - int64_t t1 = get_time(); - printf("consumer: t1=%lld µs\n", (long long)t1/1000); - #endif - - assert(needed == 0); - #ifdef DEBUG - printf("consumer: needed <- %zu\n", len); - #endif - needed = len; - pthread_cond_signal(&need); - - #ifdef DEBUG - printf("consumer: waiting for data\n"); - #endif - pthread_cond_wait(&avail, &m); - assert(needed == 0); - assert(available == len); - - #ifdef DEBUG - int64_t t2 = get_time(); - printf("consumer: t2=%lld µs\n", (long long)t2/1000); - if(t1>0 && t2>0) { - uint64_t latency = t2-t1; - cummulativeLatency += latency; - numCallbacks++; - printf("consumer: latency=%lld µs, avg=%u µs\n", - (long long)(latency/1000), - (unsigned)(cummulativeLatency/numCallbacks/1000)); - } - #endif - } - - #ifdef DEBUG - printf("consumer: received %zu bytes of data\n", available); - printf("consumer: available <- 0\n"); - #endif - available = 0; - stream = NULL; - } - pthread_mutex_unlock(&m); -// SDL_UnlockAudio(); -} - -callback_t callback_getCallback() { - return &callback; -} - -void callback_fillBuffer(Uint8 *data, size_t numBytes) { - size_t sent = 0; - - pthread_mutex_lock(&m); - - while(sent < numBytes) { - #ifdef DEBUG - int64_t t = get_time(); - printf("producer: t=%lld µs\n", (long long)t/1000); - #endif - - if(needed == 0) { - #ifdef DEBUG - printf("producer: waiting until data is needed (1)\n"); - #endif - pthread_cond_wait(&need, &m); - - // Interrupted from 'callback_unblock' ? - if(needed == 0) { - #ifdef DEBUG - printf("producer: interrupted (1)\n"); - #endif - break; - } - } - - assert(stream != NULL); - assert(needed > 0); - - // Append a chunk of data to the 'stream' - size_t n = (needed<(numBytes-sent)) ? needed : (numBytes-sent); - memcpy(stream+available, data+sent, n); - available += n; - sent += n; - needed -= n; - - #ifdef DEBUG - printf("producer: added %zu bytes, available=%zu\n", n, available); - #endif - - if(needed == 0) { - pthread_cond_signal(&avail); - if(sent < numBytes) { - #ifdef DEBUG - printf("producer: waiting until data is needed (2)\n"); - #endif - pthread_cond_wait(&need, &m); - - // Interrupted from 'callback_unblock' ? - if(needed == 0) { - #ifdef DEBUG - printf("producer: interrupted (2)\n"); - #endif - break; - } - } - else { - break; - } - } - } - - pthread_mutex_unlock(&m); -} - -void callback_unblock() { - pthread_mutex_lock(&m); - if(needed > 0) { - // Note: SDL already prefilled the entire 'stream' with silence - assert(stream != NULL); - available += needed; - needed = 0; - pthread_cond_signal(&avail); - } - pthread_cond_signal(&need); - pthread_mutex_unlock(&m); -} - From ea866eebf053a527347a3aab56e2867d0bf9fb0d Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 20:43:40 +0100 Subject: [PATCH 64/79] reorganizing --- {sdl-test => examples}/Fontin Sans.otf | Bin {sdl-test => examples}/test.go | 0 {sdl-test => examples}/test.ogg | Bin {sdl-test => examples}/test.png | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename {sdl-test => examples}/Fontin Sans.otf (100%) rename {sdl-test => examples}/test.go (100%) rename {sdl-test => examples}/test.ogg (100%) rename {sdl-test => examples}/test.png (100%) diff --git a/sdl-test/Fontin Sans.otf b/examples/Fontin Sans.otf similarity index 100% rename from sdl-test/Fontin Sans.otf rename to examples/Fontin Sans.otf diff --git a/sdl-test/test.go b/examples/test.go similarity index 100% rename from sdl-test/test.go rename to examples/test.go diff --git a/sdl-test/test.ogg b/examples/test.ogg similarity index 100% rename from sdl-test/test.ogg rename to examples/test.ogg diff --git a/sdl-test/test.png b/examples/test.png similarity index 100% rename from sdl-test/test.png rename to examples/test.png From b9ad40f255c9888d17ee488bdd6e4c94b993c725 Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 20:46:48 +0100 Subject: [PATCH 65/79] updated README.md --- README.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 741a104..544aaf3 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,11 @@ # Introduction -This is an improved version of Banthar's [Go-SDL](http://github.com/banthar/Go-SDL). +This is an improved version of 0xe2-0x9a-0x9b's [Go-SDL](https://github.com/0xe2-0x9a-0x9b/Go-SDL). The improvements/differences are: -* SDL functions (except for SDL-mixer) can be safely called from concurrently - running goroutines -* All SDL events are delivered via a Go channel -* Support for low-level SDL sound functions - -* Can be installed in parallel to Banthar's Go-SDL -* The import paths are "github.com/0xe2-0x9a-0x9b/Go-SDL/..." - +* audio callback support using excellent [Roger Peppe's callback package](http://code.google.com/p/rog-go/) +* downstreaming support (written by neagix) # Installation @@ -19,7 +13,8 @@ Make sure you have SDL, SDL-image, SDL-mixer and SDL-ttf (all in -dev version). Installing libraries and examples: - go get -v github.com/0xe2-0x9a-0x9b/Go-SDL/... + go get -v github.com/neagix/Go-SDL/sdl + go get -v github.com/neagix/Go-SDL/sdl/audio # Credits From cac5cbc992dfea32387ceb7b1f892b7ac8aa8d60 Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 20:47:31 +0100 Subject: [PATCH 66/79] reorganizing --- examples/{ => completeTest}/Fontin Sans.otf | Bin examples/{ => completeTest}/test.go | 0 examples/{ => completeTest}/test.ogg | Bin examples/{ => completeTest}/test.png | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => completeTest}/Fontin Sans.otf (100%) rename examples/{ => completeTest}/test.go (100%) rename examples/{ => completeTest}/test.ogg (100%) rename examples/{ => completeTest}/test.png (100%) diff --git a/examples/Fontin Sans.otf b/examples/completeTest/Fontin Sans.otf similarity index 100% rename from examples/Fontin Sans.otf rename to examples/completeTest/Fontin Sans.otf diff --git a/examples/test.go b/examples/completeTest/test.go similarity index 100% rename from examples/test.go rename to examples/completeTest/test.go diff --git a/examples/test.ogg b/examples/completeTest/test.ogg similarity index 100% rename from examples/test.ogg rename to examples/completeTest/test.ogg diff --git a/examples/test.png b/examples/completeTest/test.png similarity index 100% rename from examples/test.png rename to examples/completeTest/test.png From 336d7f949ddc431501105078256f03885fcd2da4 Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 21:07:54 +0100 Subject: [PATCH 67/79] added buzzer example --- examples/callback/buzzer.go | 149 ++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 examples/callback/buzzer.go diff --git a/examples/callback/buzzer.go b/examples/callback/buzzer.go new file mode 100644 index 0000000..8c17ed8 --- /dev/null +++ b/examples/callback/buzzer.go @@ -0,0 +1,149 @@ +/* + * Copyright neagix 2013 + * This sample is part of langwar project + * https://github.com/neagix/langwar + * + * Licensed under GNU/GPL v2 + */ + +package main + +import "github.com/neagix/Go-SDL/sdl/audio" +import "math" +import "time" + +type BeepObject struct { + Freq float64 + SamplesLeft int +} + +var Play chan BeepObject + +const AMPLITUDE = 28000 +const FREQUENCY = 44100 +const AUDIO_SAMPLES = 2048 + +func Beep(freq, duration int) { + bo := BeepObject{ + Freq: float64(freq), + SamplesLeft: duration * FREQUENCY / 1000} + + Play <- bo +} + +func Init() bool { + + desiredSpec := audio.AudioSpec{ + Freq: FREQUENCY, + Format: audio.AUDIO_S16SYS, + Channels: 1, + Samples: AUDIO_SAMPLES, + } + var obtainedSpec audio.AudioSpec + + if audio.OpenAudio(&desiredSpec, &obtainedSpec) != 0 { + return false + } + + Play = make(chan BeepObject) + + // start the playback queue processor + go func() { + for { + // pick next beep object + bo := <-Play + + stream := make([]int16, bo.SamplesLeft) + + v := float64(0) + for i := 0; i < bo.SamplesLeft; i++ { + stream[i] = int16(AMPLITUDE * math.Sin(v*2*math.Pi/FREQUENCY)) + v += bo.Freq + } + + audio.SendAudio_int16(stream) + } + }() + + return true +} + +// to be deferred after corresponding Init() +func Quit() { + defer audio.CloseAudio() +} + +// song by niniel1 as found at http://gendou.com/t/20439 +func PlaySong1() { + Beep(349, 400) + time.Sleep(time.Millisecond * 33) + Beep(392, 133) + time.Sleep(time.Millisecond * 33) + Beep(440, 267) + time.Sleep(time.Millisecond * 33) + Beep(440, 267) + time.Sleep(time.Millisecond * 33) + Beep(392, 133) + time.Sleep(time.Millisecond * 33) + Beep(349, 133) + time.Sleep(time.Millisecond * 33) + Beep(392, 133) + time.Sleep(time.Millisecond * 33) + Beep(440, 133) + time.Sleep(time.Millisecond * 33) + Beep(349, 267) + time.Sleep(time.Millisecond * 33) + Beep(262, 267) + time.Sleep(time.Millisecond * 33) + Beep(349, 400) + time.Sleep(time.Millisecond * 33) + Beep(392, 133) + time.Sleep(time.Millisecond * 33) + Beep(440, 267) + time.Sleep(time.Millisecond * 33) + Beep(440, 267) + time.Sleep(time.Millisecond * 33) + Beep(392, 133) + time.Sleep(time.Millisecond * 33) + Beep(349, 133) + time.Sleep(time.Millisecond * 33) + Beep(392, 133) + time.Sleep(time.Millisecond * 33) + Beep(440, 133) + time.Sleep(time.Millisecond * 33) + Beep(349, 533) + time.Sleep(time.Millisecond * 33) +} + +// find out more songs at https://github.com/binarypearl/beepbeep +func PlaySong3() { + Beep(784, 100) + Beep(784, 100) + Beep(784, 100) + time.Sleep(time.Millisecond * 100) + Beep(784, 600) + Beep(622, 600) + Beep(698, 600) + Beep(784, 200) + time.Sleep(time.Millisecond * 200) + Beep(698, 200) + Beep(784, 800) + +} + +func main() { + if !Init() { + return + } + defer Quit() + + // start playback, yeah! + audio.PauseAudio(false) + + PlaySong1() + + // it's a silence :) + Beep(0, 400) + + PlaySong3() +} From 0c18d50d78100dc9572d5a9263793681645c8e3d Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 21:08:31 +0100 Subject: [PATCH 68/79] some bugfixes prospecting support for other formats --- sdl/audio/audio.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 2471178..3f30a19 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -87,8 +87,10 @@ const ( ) type AudioEvent struct { - Event int - Buffer []int16 + Event int + Buffer []int16 + + AudioType int } // Audio status @@ -100,15 +102,15 @@ const ( var PlayLoop chan AudioEvent var PlayQueueSize int -var TailBuffer []int16 +var TailBufferS16 []int16 //NOTE: we assume this is not going to be called concurrently :) -func DownstreamPlayback16(buffer unsafe.Pointer, bufferSize int) { +func DownstreamPlaybackS16(buffer unsafe.Pointer, bufferSize int) { // hack to convert C void* pointer to proper Go slice var stream []int16 streamLen := bufferSize / 2 - tailBufferLen := len(TailBuffer) + tailBufferLen := len(TailBufferS16) sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&stream))) sliceHeader.Cap = streamLen sliceHeader.Len = streamLen @@ -119,22 +121,22 @@ func DownstreamPlayback16(buffer unsafe.Pointer, bufferSize int) { // first thing, pick any eventual remnants buffer to copy over dstOffset := 0 - if nil != TailBuffer && tailBufferLen > 0 { - for i := range TailBuffer { - stream[dstOffset] = TailBuffer[i] + if nil != TailBufferS16 && tailBufferLen > 0 { + for i := range TailBufferS16 { + stream[dstOffset] = TailBufferS16[i] dstOffset++ // we have copied enough if dstOffset == streamLen { - newTailBuffer := make([]int16, tailBufferLen-dstOffset) - copy(newTailBuffer, TailBuffer[dstOffset:]) - TailBuffer = newTailBuffer + newTailBufferS16 := make([]int16, tailBufferLen-dstOffset) + copy(newTailBufferS16, TailBufferS16[dstOffset:]) + TailBufferS16 = newTailBufferS16 return } } - // we have consumed the whole TailBuffer, reset it - TailBuffer = nil + // we have consumed the whole TailBufferS16, reset it + TailBufferS16 = nil } // pick next beep object @@ -164,12 +166,12 @@ func DownstreamPlayback16(buffer unsafe.Pointer, bufferSize int) { toBeCopied := streamLen - dstOffset overflowingSamples := len(ae.Buffer) - toBeCopied if overflowingSamples > 0 { - TailBuffer = make([]int16, overflowingSamples) + TailBufferS16 = make([]int16, overflowingSamples) } copy(stream[dstOffset:], ae.Buffer) if overflowingSamples > 0 { - copy(TailBuffer, ae.Buffer[toBeCopied:]) + copy(TailBufferS16, ae.Buffer[toBeCopied:]) } // we have "eaten" a sound object from the queue @@ -204,7 +206,7 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { if nil != desired.UserDefinedCallback { userDefinedCallback = desired.UserDefinedCallback } else { - userDefinedCallback = DownstreamPlayback16 + userDefinedCallback = DownstreamPlaybackS16 PlayLoop = make(chan AudioEvent) } @@ -284,7 +286,7 @@ func PauseAudioSync(pause_on bool) { // This function blocks until all the samples are consumed by the SDL audio thread. func SendAudio_int16(data []int16) { PlayQueueSize++ - PlayLoop <- AudioEvent{Event: AE_PLAY_CONCAT, Buffer: data} + PlayLoop <- AudioEvent{Event: AE_PLAY_CONCAT, Buffer: data, AudioType: AUDIO_S16} } // Send samples to the audio device (AUDIO_U16SYS format). From e623dcb64abd99140cd0b642b70893df0c96ad47 Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 21:18:09 +0100 Subject: [PATCH 69/79] added known issues --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 544aaf3..e2c37ba 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,11 @@ The improvements/differences are: * audio callback support using excellent [Roger Peppe's callback package](http://code.google.com/p/rog-go/) * downstreaming support (written by neagix) +# Known issues + +The re-designed audio system supports only signed 16bit samples, but writing the others is as easy as a copy/paste. + + # Installation Make sure you have SDL, SDL-image, SDL-mixer and SDL-ttf (all in -dev version). From 8d24ad52445974248ed9c9138b267632a64d3be4 Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 10 Feb 2013 21:44:28 +0100 Subject: [PATCH 70/79] formatting --- examples/callback/buzzer.go | 44 ++++++++++++++++++------------------- sdl/audio/audio.go | 8 +++---- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/callback/buzzer.go b/examples/callback/buzzer.go index 8c17ed8..72f5445 100644 --- a/examples/callback/buzzer.go +++ b/examples/callback/buzzer.go @@ -34,10 +34,10 @@ func Beep(freq, duration int) { func Init() bool { desiredSpec := audio.AudioSpec{ - Freq: FREQUENCY, - Format: audio.AUDIO_S16SYS, - Channels: 1, - Samples: AUDIO_SAMPLES, + Freq: FREQUENCY, + Format: audio.AUDIO_S16SYS, + Channels: 1, + Samples: AUDIO_SAMPLES, } var obtainedSpec audio.AudioSpec @@ -45,25 +45,25 @@ func Init() bool { return false } - Play = make(chan BeepObject) + Play = make(chan BeepObject) - // start the playback queue processor - go func() { - for { - // pick next beep object - bo := <-Play + // start the playback queue processor + go func() { + for { + // pick next beep object + bo := <-Play - stream := make([]int16, bo.SamplesLeft) + stream := make([]int16, bo.SamplesLeft) - v := float64(0) - for i := 0; i < bo.SamplesLeft; i++ { - stream[i] = int16(AMPLITUDE * math.Sin(v*2*math.Pi/FREQUENCY)) - v += bo.Freq - } + v := float64(0) + for i := 0; i < bo.SamplesLeft; i++ { + stream[i] = int16(AMPLITUDE * math.Sin(v*2*math.Pi/FREQUENCY)) + v += bo.Freq + } - audio.SendAudio_int16(stream) - } - }() + audio.SendAudio_int16(stream) + } + }() return true } @@ -128,7 +128,7 @@ func PlaySong3() { time.Sleep(time.Millisecond * 200) Beep(698, 200) Beep(784, 800) - + } func main() { @@ -141,9 +141,9 @@ func main() { audio.PauseAudio(false) PlaySong1() - + // it's a silence :) Beep(0, 400) - + PlaySong3() } diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 3f30a19..2822316 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -87,10 +87,10 @@ const ( ) type AudioEvent struct { - Event int - Buffer []int16 - - AudioType int + Event int + Buffer []int16 + + AudioType int } // Audio status From 7fa96081be97a74f7ebbeb419a8dc7aa84f1319f Mon Sep 17 00:00:00 2001 From: Svip Date: Sat, 8 Jun 2013 14:14:01 +0200 Subject: [PATCH 71/79] Removed reference to now deleted repository (see Go-nuts list), and replaced it with "neagix", which is working (and a fork). --- ttf/ttf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttf/ttf.go b/ttf/ttf.go index 7f036d8..b6892b7 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -12,7 +12,7 @@ package ttf import "C" import ( - "github.com/0xe2-0x9a-0x9b/Go-SDL/sdl" + "github.com/neagix/Go-SDL/sdl" "sync" "unsafe" ) From b0c2a68d50f85aa6d67e3b62a6319be0532faccf Mon Sep 17 00:00:00 2001 From: neagix Date: Sun, 16 Jun 2013 16:29:18 +0200 Subject: [PATCH 72/79] Removed unnecessary callback package reference --- README.md | 10 ++++++---- sdl/audio/audio.go | 9 ++++++--- sdl/audio/callback.c | 17 +++++++++-------- sdl/audio/callback.h | 11 ++++------- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index e2c37ba..5912fba 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,19 @@ # Introduction -This is an improved version of 0xe2-0x9a-0x9b's [Go-SDL](https://github.com/0xe2-0x9a-0x9b/Go-SDL). +This is an improved version of 0xe2-0x9a-0x9b's [Go-SDL](https://github.com/0xe2-0x9a-0x9b/Go-SDL) +currently mantained by neagix. The improvements/differences are: -* audio callback support using excellent [Roger Peppe's callback package](http://code.google.com/p/rog-go/) -* downstreaming support (written by neagix) +* audio callback support +* downstreaming support + +There is a nice and fully working PC speaker buzzer example in examples/callback. # Known issues The re-designed audio system supports only signed 16bit samples, but writing the others is as easy as a copy/paste. - # Installation Make sure you have SDL, SDL-image, SDL-mixer and SDL-ttf (all in -dev version). diff --git a/sdl/audio/audio.go b/sdl/audio/audio.go index 2822316..824099b 100644 --- a/sdl/audio/audio.go +++ b/sdl/audio/audio.go @@ -23,7 +23,6 @@ package audio import "C" import "unsafe" import "reflect" -import "code.google.com/p/rog-go/exp/callback" // The version of Go-SDL audio bindings. // The version descriptor changes into a new unique string @@ -34,11 +33,13 @@ import "code.google.com/p/rog-go/exp/callback" // // If Go adds some kind of support for package versioning, this function will go away. func GoSdlAudioVersion() string { - return "Go-SDL audio 1.1" + return "Go-SDL audio 1.2" } var userDefinedCallback func(unsafe.Pointer, int) +// this is the callback called from the C code +// without any special glue since the CGO threads insanity has been fixed =) //export streamCallback func streamCallback(arg unsafe.Pointer) { ctx := (*C.context)(arg) @@ -196,7 +197,6 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { panic("more than 1 audio stream currently not supported") } - C.setCallbackFunc(callback.Func) // copy handle to user-defined callback function, if defined // it is perfectly supported to not specify the callback function // in that case you will use default SendAudio semantics @@ -206,6 +206,7 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { if nil != desired.UserDefinedCallback { userDefinedCallback = desired.UserDefinedCallback } else { + // default playback (16-bit signed) userDefinedCallback = DownstreamPlaybackS16 PlayLoop = make(chan AudioEvent) } @@ -217,6 +218,8 @@ func OpenAudio(desired, obtained_orNil *AudioSpec) int { C_desired.format = C.Uint16(desired.Format) C_desired.channels = C.Uint8(desired.Channels) C_desired.samples = C.Uint16(desired.Samples) + // there is an unique C callback acting as proxy to the different Go callbacks + // see streamContext() C_desired.callback = C.callback_getCallback() if obtained_orNil != nil { diff --git a/sdl/audio/callback.c b/sdl/audio/callback.c index ae824fb..c213dc3 100644 --- a/sdl/audio/callback.c +++ b/sdl/audio/callback.c @@ -1,29 +1,30 @@ /* + * Copyright neagix - Feb 2013 * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 + * * * The contents of this file can be used freely, * except for usages in immoral contexts. + * */ +/* +An interface to low-level SDL sound functions +with support for callbacks and rudimentary stream mixing +*/ + #include "callback.h" #include #include #include #include "_cgo_export.h" -// callbackFunc holds the callback library function. -// It is stored in a function pointer because C linkage -// does not work across packages. -static void(*callbackFunc)(void (*f)(void*), void*); - -void setCallbackFunc(void *cb){ callbackFunc = cb; } - static void SDLCALL callback(void *userdata, Uint8 *_stream, int len) { SDL_LockAudio(); context context = { _stream, len }; - callbackFunc(streamCallback, &context); + streamCallback(&context); SDL_UnlockAudio(); } diff --git a/sdl/audio/callback.h b/sdl/audio/callback.h index 5ac0a81..b2874a7 100644 --- a/sdl/audio/callback.h +++ b/sdl/audio/callback.h @@ -1,10 +1,13 @@ /* + * Copyright neagix - Feb 2013 * Copyright: ⚛ <0xe2.0x9a.0x9b@gmail.com> 2010 + * * * The contents of this file can be used freely, * except for usages in immoral contexts. + * */ - + #ifndef __CALLBACK_H #define __CALLBACK_H @@ -19,11 +22,5 @@ struct context { typedef void (SDLCALL *callback_t)(void *userdata, Uint8 *stream, int len); extern callback_t callback_getCallback(); -//extern void callback_fillBuffer(Uint8 *data, size_t numBytes); -//extern void callback_unblock(); - -// from pa.c -extern void setCallbackFunc(void *cb); -extern int paStreamCallback(void *outputBuffer, unsigned long bytesCount); #endif //__CALLBACK_H From 4e897366e09430d226e7d43b9f961e8712898952 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Sun, 23 Jun 2013 00:35:34 +0200 Subject: [PATCH 73/79] Adds minimal support for SDL's RWops. At the moment, only 2 functions are implemented: 1) RWFromMem(but []byte) Creates a RWops from memory 2) IMG_Load_RW(rwOps *RWops) Loads an image from an RWops --- sdl/rwops.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 sdl/rwops.go diff --git a/sdl/rwops.go b/sdl/rwops.go new file mode 100644 index 0000000..5c350cb --- /dev/null +++ b/sdl/rwops.go @@ -0,0 +1,43 @@ +package sdl + +import ( + "log" + "unsafe" +) + +// #cgo pkg-config: sdl +// #include +import "C" + +type RWops struct { + cRWops *C.SDL_RWops + + gcBytes []byte // Prevents garbage collection of memory passed to RWFromMem +} + +func (s *RWops) destroy() { + s.cRWops = nil + s.gcBytes = nil +} + +// Creates an RWops from memory. +func RWFromMem(buf []byte) *RWops { + GlobalMutex.Lock() + defer GlobalMutex.Unlock() + + p := C.SDL_RWFromMem(unsafe.Pointer(&buf[0]), C.int(len(buf))) + var rwops RWops + rwops.cRWops = (*C.SDL_RWops)(p) + rwops.gcBytes = buf + return &rwops + +} + +func (self *RWops) Free() { + GlobalMutex.Lock() + defer GlobalMutex.Unlock() + + C.SDL_FreeRW(self.cRWops) + self.cRWops = nil + self.gcBytes = nil +} From 6fbb04ad4a1b785ead9e28d77d732b5bcf33e49d Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Sun, 23 Jun 2013 00:40:30 +0200 Subject: [PATCH 74/79] Adds minimal support for SDL's RWops. At the moment, only 2 functions are implemented: 1) RWFromMem(but []byte) Creates a RWops from memory 2) IMG_Load_RW(rwOps *RWops) Loads an image from an RWops --- sdl/sdl.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sdl/sdl.go b/sdl/sdl.go index 9596004..36415a6 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -550,6 +550,17 @@ func Load(file string) *Surface { return wrap(screen) } +// Loads Surface from file (using IMG_Load). +func Load_RW(rwOps *RWops) *Surface { + GlobalMutex.Lock() + + var screen = C.IMG_Load_RW((*C.SDL_RWops)(cast(rwOps.cRWops)), 0) + + GlobalMutex.Unlock() + + return wrap(screen) +} + // SaveBMP saves the src surface as a Windows BMP to file. func (src *Surface) SaveBMP(file string) int { GlobalMutex.Lock() From be9133e255a8aa4833372566d86379c06612a008 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Sun, 23 Jun 2013 00:42:19 +0200 Subject: [PATCH 75/79] fixed comment --- sdl/sdl.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdl/sdl.go b/sdl/sdl.go index 36415a6..aceeb47 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -550,7 +550,7 @@ func Load(file string) *Surface { return wrap(screen) } -// Loads Surface from file (using IMG_Load). +// Loads Surface from RWops (using IMG_Load_RW). func Load_RW(rwOps *RWops) *Surface { GlobalMutex.Lock() From 898801ae8cb445637600ddb23fc5badc1a56dfa2 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Sun, 23 Jun 2013 00:52:21 +0200 Subject: [PATCH 76/79] removed unused imports --- sdl/rwops.go | 1 - 1 file changed, 1 deletion(-) diff --git a/sdl/rwops.go b/sdl/rwops.go index 5c350cb..f4c825e 100644 --- a/sdl/rwops.go +++ b/sdl/rwops.go @@ -1,7 +1,6 @@ package sdl import ( - "log" "unsafe" ) From aa7077673d4d5c0a4d872d31801e70f878b5e992 Mon Sep 17 00:00:00 2001 From: telecoda Date: Wed, 17 Jul 2013 00:12:59 +0100 Subject: [PATCH 77/79] remove references to old git repo --- examples/completeTest/test.go | 8 ++++---- sdl-template/template.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/completeTest/test.go b/examples/completeTest/test.go index 11dc9db..5ad2fa3 100644 --- a/examples/completeTest/test.go +++ b/examples/completeTest/test.go @@ -2,9 +2,9 @@ package main import ( "fmt" - "github.com/0xe2-0x9a-0x9b/Go-SDL/mixer" - "github.com/0xe2-0x9a-0x9b/Go-SDL/sdl" - "github.com/0xe2-0x9a-0x9b/Go-SDL/ttf" + "github.com/neagix/Go-SDL/mixer" + "github.com/neagix/Go-SDL/sdl" + "github.com/neagix/Go-SDL/ttf" "log" "math" "os" @@ -53,7 +53,7 @@ func main() { log.Fatal("No such environment variable: GOPATH") } for _, gopath := range strings.Split(GOPATH, ":") { - a := gopath + "/src/github.com/0xe2-0x9a-0x9b/Go-SDL/sdl-test" + a := gopath + "/src/github.com/neagix/Go-SDL/examples/completeTest" _, err := os.Stat(a) if err == nil { resourcePath = a diff --git a/sdl-template/template.go b/sdl-template/template.go index 2ad1fd8..7b0453e 100644 --- a/sdl-template/template.go +++ b/sdl-template/template.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/0xe2-0x9a-0x9b/Go-SDL/sdl" + "github.com/neagix/Go-SDL/sdl" "math/rand" "time" ) From f567d36e70a95f2145d644dabedac76887bd117c Mon Sep 17 00:00:00 2001 From: sqweek Date: Tue, 16 Jul 2013 20:03:09 +0800 Subject: [PATCH 78/79] Add bindings for SDL_Sound. --- examples/sound/test.go | 72 +++++++++++++++++ mixer/mixer.go | 12 +++ sound/constants.go | 9 +++ sound/sound.go | 171 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 examples/sound/test.go create mode 100644 sound/constants.go create mode 100644 sound/sound.go diff --git a/examples/sound/test.go b/examples/sound/test.go new file mode 100644 index 0000000..4d4f6ff --- /dev/null +++ b/examples/sound/test.go @@ -0,0 +1,72 @@ +package main + +import ( + "github.com/neagix/Go-SDL/sdl" + "github.com/neagix/Go-SDL/sdl/audio" + "github.com/neagix/Go-SDL/sound" + "log" + "time" + "os" + "strings" +) + +func main() { + log.SetFlags(0) + + var resourcePath string + { + GOPATH := os.Getenv("GOPATH") + if GOPATH == "" { + log.Fatal("No such environment variable: GOPATH") + } + for _, gopath := range strings.Split(GOPATH, ":") { + a := gopath + "/src/github.com/neagix/Go-SDL/examples/completeTest" + _, err := os.Stat(a) + if err == nil { + resourcePath = a + break + } + } + if resourcePath == "" { + log.Fatal("Failed to find resource directory") + } + } + + if sdl.Init(sdl.INIT_EVERYTHING) != 0 { + log.Fatal(sdl.GetError()) + } + + sound.Init() + + desiredSpec := audio.AudioSpec{Freq: 44100, Format: audio.AUDIO_S16SYS, Channels: 1, Samples: 4096} + var obtainedSpec audio.AudioSpec + + if audio.OpenAudio(&desiredSpec, &obtainedSpec) != 0 { + log.Fatal(sdl.GetError()) + } + + fmt := sound.AudioInfo{obtainedSpec.Format, obtainedSpec.Channels, uint32(obtainedSpec.Freq)} + /* note: on my machine i always get 2 channels, despite only requesting one */ + + sdl.EnableUNICODE(1) + + sample := sound.NewSampleFromFile(resourcePath+"/test.ogg", &fmt, 1048756) + + sample.DecodeAll() + buf := sample.Buffer_int16() + /* this decodes the entire file at once and loads it into memory. sample.Decode() + will decode in chunks of ~1mb, since that's the buffer size I requested above. */ + + audio.PauseAudio(false) + + audio.SendAudio_int16(buf) + /* note: this sends the entire buffer to the audio system at once, which + is a stupid thing to do in practice because the audio callback will block while + it copies the samples to its internal tail buffer, and won't be able to fill the + current audio frame in a timely manner. this will cause many underruns. + A better approach is to call SendAudio in a loop with small chunks of the + buffer at a time. */ + + time.Sleep(time.Second * 45) + /* we better stick around or we'll exit before making any noise! */ +} diff --git a/mixer/mixer.go b/mixer/mixer.go index 9b71ba4..59b3195 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -24,6 +24,18 @@ func OpenAudio(frequency int, format uint16, channels, chunksize int) int { C.int(channels), C.int(chunksize))) } +// Queries the mixer format. Returns (0,0,0) if audio has not been +// opened, and (frequency, format, channels) otherwise +func QuerySpec() (int, uint16, int) { + var frequency C.int + var format C.Uint16 + var channels C.int + if C.Mix_QuerySpec(&frequency, &format, &channels) == 0 { + return 0, 0, 0 + } + return int(frequency), uint16(format), int(channels) +} + // Shuts down SDL_mixer. func CloseAudio() { C.Mix_CloseAudio() } diff --git a/sound/constants.go b/sound/constants.go new file mode 100644 index 0000000..b2a3335 --- /dev/null +++ b/sound/constants.go @@ -0,0 +1,9 @@ +package sound + +const ( + SAMPLEFLAG_NONE = 0 + SAMPLEFLAG_CANSEEK = 1 + SAMPLEFLAG_EOF = 1 << 29 + SAMPLEFLAG_ERROR = 1 << 30 // unrecoverable error + SAMPLEFLAG_EAGAIN = 1 << 31 // function would block or temp error +) diff --git a/sound/sound.go b/sound/sound.go new file mode 100644 index 0000000..1fa0914 --- /dev/null +++ b/sound/sound.go @@ -0,0 +1,171 @@ +/* +A binding of SDL_sound. + +Currently NewSampleFromFile() is the only way to create a Sample struct, the +core focus of the API. From there you can call Sample.Decode()/DecodeAll() +followed by Sample.Buffer_int16() to get at the decoded sound samples. + +Signed 16-bit ints is the only supported audio format at the moment. +*/ +package sound + +// #cgo pkg-config: sdl +// #include +// #cgo LDFLAGS: -lSDL_sound +import "C" +import "unsafe" + +import "sync" +import "github.com/neagix/Go-SDL/sdl/audio" + +type AudioInfo struct { + Format uint16 + Channels uint8 + Rate uint32 +} + +type DecoderInfo struct { + Extensions []string // a list of valid extensions + Description string // human readable description + Author string + Url string +} + +type Sample struct { + sync.Mutex + csample *C.Sound_Sample + Decoder *DecoderInfo + Desired *AudioInfo + Actual *AudioInfo +} + +func GetError() string { + err := C.GoString(C.Sound_GetError()) + C.Sound_ClearError() + return err +} + +func Init() int { + i, _ := C.Sound_Init() + return int(i) +} + +func Quit() int { + i, _ := C.Sound_Quit() + return int(i) +} + +func fromCDecoderInfo(cinfo *C.Sound_DecoderInfo) *DecoderInfo { + if cinfo == nil { + return nil + } + info := DecoderInfo{} + extptr := uintptr(unsafe.Pointer((*cinfo).extensions)) + for { + ext := (**C.char)(unsafe.Pointer(extptr)) + if *ext == nil { + break + } + info.Extensions = append(info.Extensions, C.GoString(*ext)) + extptr += unsafe.Sizeof(extptr) + } + info.Description = C.GoString((*cinfo).description) + info.Author = C.GoString((*cinfo).author) + info.Url = C.GoString((*cinfo).url) + return &info +} + +func AvailableDecoders() []DecoderInfo { + cinfo, _ := C.Sound_AvailableDecoders() + infos := make([]DecoderInfo, 0, 16) + infptr := uintptr(unsafe.Pointer(cinfo)) + for { + cinfo = (**C.Sound_DecoderInfo)(unsafe.Pointer(infptr)) + if *cinfo == nil { + break + } + infos = append(infos, *fromCDecoderInfo(*cinfo)) + infptr += unsafe.Sizeof(infptr) + } + return infos +} + +func fromCAudioInfo(cinfo *C.Sound_AudioInfo) *AudioInfo { + if cinfo == nil { + return nil + } + return &AudioInfo{uint16(cinfo.format), uint8(cinfo.channels), uint32(cinfo.rate)} +} + +func cAudioInfo(info *AudioInfo) *C.Sound_AudioInfo { + if info == nil { + return nil + } + cinfo := new(C.Sound_AudioInfo) + cinfo.format = C.Uint16(info.Format) + cinfo.channels = C.Uint8(info.Channels) + cinfo.rate = C.Uint32(info.Rate) + return cinfo +} + +func NewSampleFromFile(filename string, desired *AudioInfo, size uint) *Sample { + sample := new(Sample) + cfile := C.CString(filename) + defer C.free(unsafe.Pointer(cfile)) + sample.csample = C.Sound_NewSampleFromFile(cfile, cAudioInfo(desired), C.Uint32(size)) + sample.Decoder = fromCDecoderInfo(sample.csample.decoder) + sample.Desired = fromCAudioInfo(&sample.csample.desired) + sample.Actual = fromCAudioInfo(&sample.csample.actual) + return sample +} + +func FreeSample(sample Sample) { + C.Sound_FreeSample(sample.csample) +} + +func (sample *Sample) SetBufferSize(size uint32) int { + ret := C.Sound_SetBufferSize(sample.csample, C.Uint32(size)) + return int(ret) +} + +func (sample *Sample) Decode() uint32 { + sample.Lock() + defer sample.Unlock() + nbytes := C.Sound_Decode(sample.csample) + return uint32(nbytes) +} + +func (sample *Sample) DecodeAll() uint32 { + sample.Lock() + defer sample.Unlock() + nbytes := C.Sound_DecodeAll(sample.csample) + return uint32(nbytes) +} + +func (sample *Sample) Rewind() int { + ret := C.Sound_Rewind(sample.csample) + return int(ret) +} + +func (sample *Sample) Seek(ms uint32) int { + ret := C.Sound_Seek(sample.csample, C.Uint32(ms)) + return int(ret) +} + +func (sample *Sample) Flags() uint { + return uint(sample.csample.flags) +} + +func (sample *Sample) Buffer_int16() []int16 { + sample.Lock() + defer sample.Unlock() + if sample.Desired.Format != audio.AUDIO_S16SYS { + panic("wrong format requested") + } + + buf := make([]int16, int(sample.csample.buffer_size)/2) + for i := 0; i < len(buf); i++ { + buf[i] = int16(*((*C.int16_t)(unsafe.Pointer((uintptr(sample.csample.buffer) + uintptr(i*2)))))) + } + return buf +} From 3f8ef94f1c55124cd9e513177244b864affb44d1 Mon Sep 17 00:00:00 2001 From: sqweek Date: Wed, 8 Jan 2014 02:24:40 +0800 Subject: [PATCH 79/79] SDL_sound: Various fixes/cleanup. NewSampleFromFile() tried to dereference a null pointer if the corresponding C call failed. The Go signature has changed and it now returns an error in this case. GetError() now returns an error instead of string. Buffer_int16() always returned a full buffersize worth of samples, even if the entire buffer was not read in the last call to Decode()/DecodeAll() (eg. at EOF). It now only returns the samples that were actually read. --- sound/sound.go | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/sound/sound.go b/sound/sound.go index 1fa0914..00a6569 100644 --- a/sound/sound.go +++ b/sound/sound.go @@ -15,7 +15,9 @@ package sound import "C" import "unsafe" +import "errors" import "sync" +import "fmt" import "github.com/neagix/Go-SDL/sdl/audio" type AudioInfo struct { @@ -37,12 +39,14 @@ type Sample struct { Decoder *DecoderInfo Desired *AudioInfo Actual *AudioInfo + + nbytes uint32 // number of bytes read in last Decode() } -func GetError() string { - err := C.GoString(C.Sound_GetError()) +func GetError() error { + errstr := C.GoString(C.Sound_GetError()) C.Sound_ClearError() - return err + return errors.New(errstr) } func Init() int { @@ -108,15 +112,18 @@ func cAudioInfo(info *AudioInfo) *C.Sound_AudioInfo { return cinfo } -func NewSampleFromFile(filename string, desired *AudioInfo, size uint) *Sample { +func NewSampleFromFile(filename string, desired *AudioInfo, size uint) (*Sample, error) { sample := new(Sample) cfile := C.CString(filename) defer C.free(unsafe.Pointer(cfile)) sample.csample = C.Sound_NewSampleFromFile(cfile, cAudioInfo(desired), C.Uint32(size)) + if sample.csample == nil { + return nil, GetError() + } sample.Decoder = fromCDecoderInfo(sample.csample.decoder) sample.Desired = fromCAudioInfo(&sample.csample.desired) sample.Actual = fromCAudioInfo(&sample.csample.actual) - return sample + return sample, nil } func FreeSample(sample Sample) { @@ -128,18 +135,20 @@ func (sample *Sample) SetBufferSize(size uint32) int { return int(ret) } +/* Decodes as many samples as will fit in the buffer. + * Returns the number of BYTES read (zero at EOF). */ func (sample *Sample) Decode() uint32 { sample.Lock() defer sample.Unlock() - nbytes := C.Sound_Decode(sample.csample) - return uint32(nbytes) + sample.nbytes = uint32(C.Sound_Decode(sample.csample)) + return sample.nbytes } func (sample *Sample) DecodeAll() uint32 { sample.Lock() defer sample.Unlock() - nbytes := C.Sound_DecodeAll(sample.csample) - return uint32(nbytes) + sample.nbytes = uint32(C.Sound_DecodeAll(sample.csample)) + return sample.nbytes } func (sample *Sample) Rewind() int { @@ -160,10 +169,10 @@ func (sample *Sample) Buffer_int16() []int16 { sample.Lock() defer sample.Unlock() if sample.Desired.Format != audio.AUDIO_S16SYS { - panic("wrong format requested") + panic(fmt.Sprintf("wrong format requested %d", sample.Desired.Format)) } - buf := make([]int16, int(sample.csample.buffer_size)/2) + buf := make([]int16, int(sample.nbytes)/2) for i := 0; i < len(buf); i++ { buf[i] = int16(*((*C.int16_t)(unsafe.Pointer((uintptr(sample.csample.buffer) + uintptr(i*2)))))) }