From e63b3aa8533ca7df4bb6e14e5a17721416ef04bd Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Wed, 26 Jun 2013 01:02:21 +0200 Subject: [PATCH 01/10] Don't start an event poller goroutine if running under Windows. --- sdl/event.go | 81 +++++++++++++++++--------------------------- sdl/event_generic.go | 36 ++++++++++++++++++++ sdl/sdl.go | 2 +- 3 files changed, 68 insertions(+), 51 deletions(-) create mode 100644 sdl/event_generic.go diff --git a/sdl/event.go b/sdl/event.go index a21e2ca..2af0b83 100644 --- a/sdl/event.go +++ b/sdl/event.go @@ -1,65 +1,46 @@ 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, sdl.JoyAxisEvent, sdl.JoyButtonEvent, sdl.JoyHatEvent, -// sdl.JoyBallEvent -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 +// Polls all SDL events that are currently available. +func PollEvents() []interface{} { + events := make([]interface{}, 0) event := &Event{} + for event.Poll() { + var cookedEvent interface{} + switch event.Type { + case QUIT: + cookedEvent = (*QuitEvent)(cast(event)) - for { - for event.poll() { - switch event.Type { - case QUIT: - events <- *(*QuitEvent)(cast(event)) - - case KEYDOWN, KEYUP: - events <- *(*KeyboardEvent)(cast(event)) + case KEYDOWN, KEYUP: + cookedEvent = *(*KeyboardEvent)(cast(event)) - case MOUSEBUTTONDOWN, MOUSEBUTTONUP: - events <- *(*MouseButtonEvent)(cast(event)) + case MOUSEBUTTONDOWN, MOUSEBUTTONUP: + cookedEvent = *(*MouseButtonEvent)(cast(event)) - case MOUSEMOTION: - events <- *(*MouseMotionEvent)(cast(event)) + case MOUSEMOTION: + cookedEvent = *(*MouseMotionEvent)(cast(event)) - case JOYAXISMOTION: - events <- *(*JoyAxisEvent)(cast(event)) + case JOYAXISMOTION: + cookedEvent = *(*JoyAxisEvent)(cast(event)) - case JOYBUTTONDOWN, JOYBUTTONUP: - events <- *(*JoyButtonEvent)(cast(event)) + case JOYBUTTONDOWN, JOYBUTTONUP: + cookedEvent = *(*JoyButtonEvent)(cast(event)) - case JOYHATMOTION: - events <- *(*JoyHatEvent)(cast(event)) + case JOYHATMOTION: + cookedEvent = *(*JoyHatEvent)(cast(event)) - case JOYBALLMOTION: - events <- *(*JoyBallEvent)(cast(event)) + case JOYBALLMOTION: + cookedEvent = *(*JoyBallEvent)(cast(event)) - case ACTIVEEVENT: - events <- *(*ActiveEvent)(cast(event)) + case ACTIVEEVENT: + cookedEvent = *(*ActiveEvent)(cast(event)) - case VIDEORESIZE: - events <- *(*ResizeEvent)(cast(event)) - } + case VIDEORESIZE: + cookedEvent = *(*ResizeEvent)(cast(event)) } - - time.Sleep(poll_interval_ms * 1e6) + if cookedEvent != nil { + events = append(events, cookedEvent) + } + event = &Event{} } -} - -func init() { - go pollEvents() + return events } diff --git a/sdl/event_generic.go b/sdl/event_generic.go new file mode 100644 index 0000000..efa7b0b --- /dev/null +++ b/sdl/event_generic.go @@ -0,0 +1,36 @@ +// +build !windows + +// On Windows, events must be handled in the thread that created +// the window, which is most probably the thread that called sdl.Init(). +// Therefore. the Events channel is not provided on Windows, and you +// need to set up your own ticker and call sdl.PollEvents() from the +// main thread. + +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, sdl.JoyAxisEvent, sdl.JoyButtonEvent, sdl.JoyHatEvent, +// sdl.JoyBallEvent +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() { + for _, event := range PollEvents() { + events <- event + } + time.Sleep(poll_interval_ms * 1e6) +} + +func init() { + go pollEvents() +} diff --git a/sdl/sdl.go b/sdl/sdl.go index aceeb47..1a3055f 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -703,7 +703,7 @@ func GetKeyName(key Key) string { // ====== // 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))) From f454386a85dadebf8456daec637ba84e73670ace Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Wed, 26 Jun 2013 01:28:36 +0200 Subject: [PATCH 02/10] don't exit pollEvents() after the first round of events --- sdl/event_generic.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sdl/event_generic.go b/sdl/event_generic.go index efa7b0b..bca7d47 100644 --- a/sdl/event_generic.go +++ b/sdl/event_generic.go @@ -25,10 +25,12 @@ const poll_interval_ms = 10 // Polls SDL events in periodic intervals. // This function does not return. func pollEvents() { - for _, event := range PollEvents() { - events <- event + for { + for _, event := range PollEvents() { + events <- event + } + time.Sleep(poll_interval_ms * 1e6) } - time.Sleep(poll_interval_ms * 1e6) } func init() { From 1029aab1fc7b2a8621722a20131e70cbd876418f Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Thu, 27 Jun 2013 18:47:25 +0200 Subject: [PATCH 03/10] add support for RWops --- ttf/ttf.go | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/ttf/ttf.go b/ttf/ttf.go index b6892b7..3b94bc2 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -12,7 +12,7 @@ package ttf import "C" import ( - "github.com/neagix/Go-SDL/sdl" + "github.com/asig/Go-SDL/sdl" "sync" "unsafe" ) @@ -43,6 +43,13 @@ func wrap(cSurface *C.SDL_Surface) *sdl.Surface { return s } +func wrapFont(cFont *C.SDL_Font) *Font { + if cfont == nil { + return nil + } + return &Font{cfont: cfont} +} + // A ttf or otf font. type Font struct { cfont *C.TTF_Font @@ -75,47 +82,53 @@ func Quit() { // Loads a font from a file at the specified point size. func OpenFont(file string, ptsize int) *Font { sdl.GlobalMutex.Lock() + defer sdl.GlobalMutex.Unlock() cfile := C.CString(file) cfont := C.TTF_OpenFont(cfile, C.int(ptsize)) C.free(unsafe.Pointer(cfile)) - sdl.GlobalMutex.Unlock() + return wrapFont(cfont) +} - if cfont == nil { - return nil - } +// Loads a font from an RWops at the specified point size. +func OpenFontRW(rwOps RWops, ptsize int) *Font { + sdl.GlobalMutex.Lock() + defer sdl.GlobalMutex.Unlock() - return &Font{cfont: cfont} + return wrapFont(C.TTF_OpenFontRW((*C.SDL_RWops)(cast(rwOps.cRWops)), 0, C.int(ptsize))_ } // 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() + defer sdl.GlobalMutex.Unlock() cfile := C.CString(file) cfont := C.TTF_OpenFontIndex(cfile, C.int(ptsize), C.long(index)) C.free(unsafe.Pointer(cfile)) - sdl.GlobalMutex.Unlock() + return wrapFont(cfont) +} - if cfont == nil { - return nil - } +// Loads a font from an RWops containing multiple font faces at the specified +// point size. +func OpenFontIndexRW(rwOps RWops, ptsize, index int) *Font { + sdl.GlobalMutex.Lock() + defer sdl.GlobalMutex.Unlock() - return &Font{cfont: cfont} + return wrapFont(C.TTF_OpenFontIndexRW((*C.SDL_RWops)(cast(rwOps.cRWops)), 0, C.int(ptsize), C.long(index))) } // Frees the pointer to the font. func (f *Font) Close() { sdl.GlobalMutex.Lock() + defer sdl.GlobalMutex.Unlock() f.mutex.Lock() + defer f.mutex.Unlock() 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 From 3f23047fdc6717ab57bd9bed1ac16fcca3fa9e96 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Wed, 10 Jul 2013 00:56:59 +0200 Subject: [PATCH 04/10] make it build --- sdl/rwops.go | 10 +++++----- sdl/sdl.go | 2 +- ttf/ttf.go | 12 +++++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/sdl/rwops.go b/sdl/rwops.go index f4c825e..b79fc7a 100644 --- a/sdl/rwops.go +++ b/sdl/rwops.go @@ -9,13 +9,13 @@ import ( import "C" type RWops struct { - cRWops *C.SDL_RWops + CRWops *C.SDL_RWops gcBytes []byte // Prevents garbage collection of memory passed to RWFromMem } func (s *RWops) destroy() { - s.cRWops = nil + s.CRWops = nil s.gcBytes = nil } @@ -26,7 +26,7 @@ func RWFromMem(buf []byte) *RWops { p := C.SDL_RWFromMem(unsafe.Pointer(&buf[0]), C.int(len(buf))) var rwops RWops - rwops.cRWops = (*C.SDL_RWops)(p) + rwops.CRWops = (*C.SDL_RWops)(p) rwops.gcBytes = buf return &rwops @@ -36,7 +36,7 @@ func (self *RWops) Free() { GlobalMutex.Lock() defer GlobalMutex.Unlock() - C.SDL_FreeRW(self.cRWops) - self.cRWops = nil + C.SDL_FreeRW(self.CRWops) + self.CRWops = nil self.gcBytes = nil } diff --git a/sdl/sdl.go b/sdl/sdl.go index 1a3055f..26a6915 100644 --- a/sdl/sdl.go +++ b/sdl/sdl.go @@ -554,7 +554,7 @@ func Load(file string) *Surface { func Load_RW(rwOps *RWops) *Surface { GlobalMutex.Lock() - var screen = C.IMG_Load_RW((*C.SDL_RWops)(cast(rwOps.cRWops)), 0) + var screen = C.IMG_Load_RW((*C.SDL_RWops)(cast(rwOps.CRWops)), 0) GlobalMutex.Unlock() diff --git a/ttf/ttf.go b/ttf/ttf.go index 3b94bc2..12ff391 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -17,6 +17,8 @@ import ( "unsafe" ) +type cast unsafe.Pointer + // The version of Go-SDL TTF bindings. // The version descriptor changes into a new unique string // after a semantically incompatible Go-SDL update. @@ -43,7 +45,7 @@ func wrap(cSurface *C.SDL_Surface) *sdl.Surface { return s } -func wrapFont(cFont *C.SDL_Font) *Font { +func wrapFont(cfont *C.TTF_Font) *Font { if cfont == nil { return nil } @@ -92,11 +94,11 @@ func OpenFont(file string, ptsize int) *Font { } // Loads a font from an RWops at the specified point size. -func OpenFontRW(rwOps RWops, ptsize int) *Font { +func OpenFontRW(rwOps sdl.RWops, ptsize int) *Font { sdl.GlobalMutex.Lock() defer sdl.GlobalMutex.Unlock() - return wrapFont(C.TTF_OpenFontRW((*C.SDL_RWops)(cast(rwOps.cRWops)), 0, C.int(ptsize))_ + return wrapFont(C.TTF_OpenFontRW((*C.SDL_RWops)(cast(rwOps.CRWops)), 0, C.int(ptsize))) } // Loads a font from a file containing multiple font faces at the specified @@ -114,11 +116,11 @@ func OpenFontIndex(file string, ptsize, index int) *Font { // Loads a font from an RWops containing multiple font faces at the specified // point size. -func OpenFontIndexRW(rwOps RWops, ptsize, index int) *Font { +func OpenFontIndexRW(rwOps sdl.RWops, ptsize, index int) *Font { sdl.GlobalMutex.Lock() defer sdl.GlobalMutex.Unlock() - return wrapFont(C.TTF_OpenFontIndexRW((*C.SDL_RWops)(cast(rwOps.cRWops)), 0, C.int(ptsize), C.long(index))) + return wrapFont(C.TTF_OpenFontIndexRW((*C.SDL_RWops)(cast(rwOps.CRWops)), 0, C.int(ptsize), C.long(index))) } // Frees the pointer to the font. From 7f5ed2b59e2aad1a5dd7ef0dcf48b92d1e303b66 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Wed, 10 Jul 2013 01:02:27 +0200 Subject: [PATCH 05/10] updated information about this Go-SDL --- README.md | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 5912fba..cb5e01f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,11 @@ # Introduction -This is an improved version of 0xe2-0x9a-0x9b's [Go-SDL](https://github.com/0xe2-0x9a-0x9b/Go-SDL) -currently mantained by neagix. +This is an improved version of neagix's improved verison of 0xe2-0x9a-0x9b's [Go-SDL](https://github.com/0xe2-0x9a-0x9b/Go-SDL). -The improvements/differences are: +The improvements over/differences to neagix's version are: -* 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. +* working event loop under Windows +* support for RWops # Installation @@ -20,8 +13,9 @@ 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/neagix/Go-SDL/sdl - go get -v github.com/neagix/Go-SDL/sdl/audio + go get -v github.com/asig/Go-SDL/sdl + go get -v github.com/asig/Go-SDL/ttf + go get -v github.com/asig/Go-SDL/sdl/audio # Credits From a8a34bf8d36f14d9c5bda76cb074103e64b95b6c Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Wed, 10 Jul 2013 01:04:03 +0200 Subject: [PATCH 06/10] typos fixed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb5e01f..c315cb3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Introduction -This is an improved version of neagix's improved verison of 0xe2-0x9a-0x9b's [Go-SDL](https://github.com/0xe2-0x9a-0x9b/Go-SDL). +This is an improved version of neagix's improved version of 0xe2-0x9a-0x9b's [Go-SDL](https://github.com/0xe2-0x9a-0x9b/Go-SDL). The improvements over/differences to neagix's version are: From 16a4fc83b25e20d1e112d77e983766262125cad8 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Wed, 10 Jul 2013 09:08:07 +0200 Subject: [PATCH 07/10] add missing event dereference --- sdl/event.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdl/event.go b/sdl/event.go index 2af0b83..fcdc9e7 100644 --- a/sdl/event.go +++ b/sdl/event.go @@ -8,7 +8,7 @@ func PollEvents() []interface{} { var cookedEvent interface{} switch event.Type { case QUIT: - cookedEvent = (*QuitEvent)(cast(event)) + cookedEvent = *(*QuitEvent)(cast(event)) case KEYDOWN, KEYUP: cookedEvent = *(*KeyboardEvent)(cast(event)) From 5157bf6663764ef7dfa44ec506c76c05ece99151 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Mon, 29 Jul 2013 00:34:26 +0200 Subject: [PATCH 08/10] use a RWOps pointer --- ttf/ttf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttf/ttf.go b/ttf/ttf.go index 12ff391..229482f 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -94,7 +94,7 @@ func OpenFont(file string, ptsize int) *Font { } // Loads a font from an RWops at the specified point size. -func OpenFontRW(rwOps sdl.RWops, ptsize int) *Font { +func OpenFontRW(rwOps *sdl.RWops, ptsize int) *Font { sdl.GlobalMutex.Lock() defer sdl.GlobalMutex.Unlock() From aca1233e13884f13af76c82fb3bd9ac51eb0927e Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Mon, 29 Jul 2013 23:46:00 +0200 Subject: [PATCH 09/10] use RWops pointer everywhere --- ttf/ttf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttf/ttf.go b/ttf/ttf.go index 229482f..1347306 100644 --- a/ttf/ttf.go +++ b/ttf/ttf.go @@ -116,7 +116,7 @@ func OpenFontIndex(file string, ptsize, index int) *Font { // Loads a font from an RWops containing multiple font faces at the specified // point size. -func OpenFontIndexRW(rwOps sdl.RWops, ptsize, index int) *Font { +func OpenFontIndexRW(rwOps *sdl.RWops, ptsize, index int) *Font { sdl.GlobalMutex.Lock() defer sdl.GlobalMutex.Unlock() From 264dbd934204406c49561f92b48baeb14360f589 Mon Sep 17 00:00:00 2001 From: Andreas Signer Date: Mon, 29 Jul 2013 23:46:27 +0200 Subject: [PATCH 10/10] add LoadMUS_RW --- mixer/mixer.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mixer/mixer.go b/mixer/mixer.go index 9b71ba4..4190d76 100644 --- a/mixer/mixer.go +++ b/mixer/mixer.go @@ -12,11 +12,15 @@ package mixer import "C" import "unsafe" +import "github.com/asig/Go-SDL/sdl" + // A music file. type Music struct { cmusic *C.Mix_Music } +type cast unsafe.Pointer + // Initializes SDL_mixer. Return 0 if successful and -1 if there were // initialization errors. func OpenAudio(frequency int, format uint16, channels, chunksize int) int { @@ -40,6 +44,15 @@ func LoadMUS(file string) *Music { return &Music{cmusic} } +// Loads a music file to use. +func LoadMUS_RW(rwOps *sdl.RWops) *Music { + cmusic := C.Mix_LoadMUS_RW((*C.SDL_RWops)(cast(rwOps.CRWops))) + if cmusic == nil { + return nil + } + return &Music{cmusic} +} + // Frees the loaded music file. func (m *Music) Free() { C.Mix_FreeMusic(m.cmusic) }