twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

load_windows.go (3562B)


      1 // Copyright 2018 The Ebiten Authors
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package glfw
     16 
     17 import (
     18 	"bytes"
     19 	"compress/gzip"
     20 	"fmt"
     21 	"io"
     22 	"io/ioutil"
     23 	"os"
     24 	"unsafe"
     25 
     26 	"golang.org/x/sys/windows"
     27 )
     28 
     29 type dll struct {
     30 	d     *windows.LazyDLL
     31 	path  string
     32 	procs map[string]*windows.LazyProc
     33 }
     34 
     35 func (d *dll) call(name string, args ...uintptr) uintptr {
     36 	if d.procs == nil {
     37 		d.procs = map[string]*windows.LazyProc{}
     38 	}
     39 	if _, ok := d.procs[name]; !ok {
     40 		d.procs[name] = d.d.NewProc(name)
     41 	}
     42 	r, _, err := d.procs[name].Call(args...)
     43 	if err != nil && err.(windows.Errno) != 0 {
     44 		// It looks like there is no way to handle these errors?
     45 		// panic(fmt.Sprintf("glfw: calling proc error: errno: %d (%s)", err, err.Error()))
     46 	}
     47 	return r
     48 }
     49 
     50 func createTempDLL(content io.Reader) (string, error) {
     51 	f, err := ioutil.TempFile("", "glfw.*.dll")
     52 	if err != nil {
     53 		return "", err
     54 	}
     55 	defer f.Close()
     56 
     57 	fn := f.Name()
     58 
     59 	if _, err := io.Copy(f, content); err != nil {
     60 		return "", err
     61 	}
     62 
     63 	return fn, nil
     64 }
     65 
     66 func loadDLL() (*dll, error) {
     67 	f, err := gzip.NewReader(bytes.NewReader(glfwDLLCompressed))
     68 	if err != nil {
     69 		return nil, err
     70 	}
     71 	defer f.Close()
     72 
     73 	fn, err := createTempDLL(f)
     74 	if err != nil {
     75 		return nil, err
     76 	}
     77 
     78 	return &dll{
     79 		d:    windows.NewLazyDLL(fn),
     80 		path: fn,
     81 	}, nil
     82 }
     83 
     84 func (d *dll) unload() error {
     85 	if err := windows.FreeLibrary(windows.Handle(d.d.Handle())); err != nil {
     86 		return err
     87 	}
     88 	if err := os.Remove(d.path); err != nil {
     89 		return err
     90 	}
     91 	return nil
     92 }
     93 
     94 func bytePtrToString(ptr *byte) string {
     95 	var bs []byte
     96 	for i := uintptr(0); ; i++ {
     97 		b := *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + i))
     98 		if b == 0 {
     99 			break
    100 		}
    101 		bs = append(bs, b)
    102 	}
    103 	return string(bs)
    104 }
    105 
    106 type glfwError struct {
    107 	code ErrorCode
    108 	desc string
    109 }
    110 
    111 func (e *glfwError) Error() string {
    112 	return fmt.Sprintf("glfw: %s: %s", e.code.String(), e.desc)
    113 }
    114 
    115 var lastErr = make(chan *glfwError, 1)
    116 
    117 func fetchError() error {
    118 	select {
    119 	case err := <-lastErr:
    120 		return err
    121 	default:
    122 		return nil
    123 	}
    124 }
    125 
    126 func panicError() {
    127 	if err := acceptError(); err != nil {
    128 		panic(err)
    129 	}
    130 }
    131 
    132 func flushErrors() {
    133 	if err := fetchError(); err != nil {
    134 		panic(fmt.Sprintf("glfw: uncaught error: %s", err))
    135 	}
    136 }
    137 
    138 func acceptError(codes ...ErrorCode) error {
    139 	err := fetchError()
    140 	if err == nil {
    141 		return nil
    142 	}
    143 	for _, c := range codes {
    144 		if err.(*glfwError).code == c {
    145 			return nil
    146 		}
    147 	}
    148 	if err.(*glfwError).code == PlatformError {
    149 		// PlatformError is not handled here (See github.com/go-gl/glfw's implementation).
    150 		// TODO: Should we log this error?
    151 		return nil
    152 	}
    153 	return err
    154 }
    155 
    156 func goGLFWErrorCallback(code uintptr, desc *byte) uintptr {
    157 	flushErrors()
    158 	err := &glfwError{
    159 		code: ErrorCode(code),
    160 		desc: bytePtrToString(desc),
    161 	}
    162 	select {
    163 	case lastErr <- err:
    164 	default:
    165 		panic(fmt.Sprintf("glfw: uncaught error: %s", err))
    166 	}
    167 	return 0
    168 }
    169 
    170 var glfwDLL *dll
    171 
    172 func init() {
    173 	dll, err := loadDLL()
    174 	if err != nil {
    175 		panic(err)
    176 	}
    177 	glfwDLL = dll
    178 
    179 	glfwDLL.call("glfwSetErrorCallback", windows.NewCallbackCDecl(goGLFWErrorCallback))
    180 }