internal/gamepad: remove Cgo on darwin (#2330)

Updates #1162
This commit is contained in:
TotallyGamerJet 2022-09-15 11:11:59 -04:00 committed by GitHub
parent 3cafb0f6fd
commit 4a569be6f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 405 additions and 117 deletions

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/hajimehoshi/ebiten/v2
go 1.16
require (
github.com/ebitengine/purego v0.0.0-20220910041003-a51c01493ff9
github.com/ebitengine/purego v0.2.0-alpha.0.20220915044048-aa1b0f680473
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad
github.com/hajimehoshi/bitmapfont/v2 v2.2.1
github.com/hajimehoshi/go-mp3 v0.3.3

4
go.sum
View File

@ -1,7 +1,7 @@
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ebitengine/purego v0.0.0-20220907032450-cf3e27c364c7/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
github.com/ebitengine/purego v0.0.0-20220910041003-a51c01493ff9 h1:SWRYqW9r4JvlnVnDurFzaF+0X60GG5QZD8n0U9cq3Gw=
github.com/ebitengine/purego v0.0.0-20220910041003-a51c01493ff9/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
github.com/ebitengine/purego v0.2.0-alpha.0.20220915044048-aa1b0f680473 h1:gvI3mxzjexvkakZNJkYRZOIWRQTGa8ucsQtQ/tN2VJk=
github.com/ebitengine/purego v0.2.0-alpha.0.20220915044048-aa1b0f680473/go.mod h1:8K86Hsai2ghNjg9h/9P9tDdLAhUNwqNg10OESLDOam8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJPCvzV9jUoVQG9GEUqIq5hjfYzXTqQ52Rh8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/hajimehoshi/bitmapfont/v2 v2.2.1 h1:y7zcy02/UgO24IL3COqYtrRZzhRucNBtmCo/SNU648k=

View File

@ -0,0 +1,138 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gamepad
import (
"unsafe"
"github.com/ebitengine/purego"
)
type _CFIndex int64
type _CFAllocatorRef uintptr
type _CFArrayRef uintptr
type _CFDictionaryRef uintptr
type _CFNumberRef uintptr
type _CFTypeRef uintptr
type _CFRunLoopRef uintptr
type _CFNumberType uintptr
type _CFStringRef uintptr
type _CFArrayCallBacks struct{}
type _CFDictionaryKeyCallBacks struct{}
type _CFDictionaryValueCallBacks struct{}
type _CFRunLoopRunResult int32
type _CFRunLoopMode = _CFStringRef
type _CFTimeInterval float64
type _CFTypeID uint64
type _CFStringEncoding uint32
var kCFAllocatorDefault _CFAllocatorRef = 0
const (
kCFStringEncodingUTF8 _CFStringEncoding = 0x08000100
)
const (
kCFNumberSInt32Type _CFNumberType = 3
kCFNumberIntType _CFNumberType = 9
)
var (
corefoundation = purego.Dlopen("CoreFoundation.framework/CoreFoundation", purego.RTLD_GLOBAL)
procCFNumberCreate = purego.Dlsym(corefoundation, "CFNumberCreate")
procCFNumberGetValue = purego.Dlsym(corefoundation, "CFNumberGetValue")
procCFArrayCreate = purego.Dlsym(corefoundation, "CFArrayCreate")
procCFArrayGetCount = purego.Dlsym(corefoundation, "CFArrayGetCount")
procCFArrayGetValueAtIndex = purego.Dlsym(corefoundation, "CFArrayGetValueAtIndex")
procCFDictionaryCreate = purego.Dlsym(corefoundation, "CFDictionaryCreate")
procCFRelease = purego.Dlsym(corefoundation, "CFRelease")
procCFRunLoopGetMain = purego.Dlsym(corefoundation, "CFRunLoopGetMain")
procCFRunLoopRunInMode = purego.Dlsym(corefoundation, "CFRunLoopRunInMode")
procCFGetTypeID = purego.Dlsym(corefoundation, "CFGetTypeID")
procCFStringGetCString = purego.Dlsym(corefoundation, "CFStringGetCString")
procCFStringCreateWithCString = purego.Dlsym(corefoundation, "CFStringCreateWithCString")
kCFTypeDictionaryKeyCallBacks = purego.Dlsym(corefoundation, "kCFTypeDictionaryKeyCallBacks")
kCFTypeDictionaryValueCallBacks = purego.Dlsym(corefoundation, "kCFTypeDictionaryValueCallBacks")
kCFTypeArrayCallBacks = purego.Dlsym(corefoundation, "kCFTypeArrayCallBacks")
kCFRunLoopDefaultMode = purego.Dlsym(corefoundation, "kCFRunLoopDefaultMode")
)
func _CFNumberCreate(allocator _CFAllocatorRef, theType _CFNumberType, valuePtr unsafe.Pointer) _CFNumberRef {
number, _, _ := purego.SyscallN(procCFNumberCreate, uintptr(allocator), uintptr(theType), uintptr(valuePtr))
return _CFNumberRef(number)
}
func _CFNumberGetValue(number _CFNumberRef, theType _CFNumberType, valuePtr unsafe.Pointer) bool {
ret, _, _ := purego.SyscallN(procCFNumberGetValue, uintptr(number), uintptr(theType), uintptr(valuePtr))
return ret != 0
}
func _CFArrayCreate(allocator _CFAllocatorRef, values *unsafe.Pointer, numValues _CFIndex, callbacks *_CFArrayCallBacks) _CFArrayRef {
ret, _, _ := purego.SyscallN(procCFArrayCreate, uintptr(allocator), uintptr(unsafe.Pointer(values)), uintptr(numValues), uintptr(unsafe.Pointer(callbacks)))
return _CFArrayRef(ret)
}
func _CFArrayGetValueAtIndex(array _CFArrayRef, index _CFIndex) uintptr {
ret, _, _ := purego.SyscallN(procCFArrayGetValueAtIndex, uintptr(array), uintptr(index))
return ret
}
func _CFArrayGetCount(array _CFArrayRef) _CFIndex {
ret, _, _ := purego.SyscallN(procCFArrayGetCount, uintptr(array))
return _CFIndex(ret)
}
func _CFDictionaryCreate(allocator _CFAllocatorRef, keys *unsafe.Pointer, values *unsafe.Pointer, numValues _CFIndex, keyCallBacks *_CFDictionaryKeyCallBacks, valueCallBacks *_CFDictionaryValueCallBacks) _CFDictionaryRef {
ret, _, _ := purego.SyscallN(procCFDictionaryCreate, uintptr(allocator), uintptr(unsafe.Pointer(keys)), uintptr(unsafe.Pointer(values)), uintptr(numValues), uintptr(unsafe.Pointer(keyCallBacks)), uintptr(unsafe.Pointer(valueCallBacks)))
return _CFDictionaryRef(ret)
}
func _CFRelease(cf _CFTypeRef) {
purego.SyscallN(procCFRelease, uintptr(cf))
}
func _CFRunLoopGetMain() _CFRunLoopRef {
ret, _, _ := purego.SyscallN(procCFRunLoopGetMain)
return _CFRunLoopRef(ret)
}
func _CFRunLoopRunInMode(mode _CFRunLoopMode, seconds _CFTimeInterval, returnAfterSourceHandled bool) _CFRunLoopRunResult {
var b uintptr = 0
if returnAfterSourceHandled {
b = 1
}
if seconds != 0 {
panic("corefoundation: seconds greater than 0 is not supported")
}
//TODO: support floats
ret, _, _ := purego.SyscallN(procCFRunLoopRunInMode, uintptr(mode), b)
return _CFRunLoopRunResult(ret)
}
func _CFGetTypeID(cf _CFTypeRef) _CFTypeID {
ret, _, _ := purego.SyscallN(procCFGetTypeID, uintptr(cf))
return _CFTypeID(ret)
}
func _CFStringGetCString(theString _CFStringRef, buffer []byte, encoding _CFStringEncoding) bool {
ret, _, _ := purego.SyscallN(procCFStringGetCString, uintptr(theString), uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(encoding))
return ret != 0
}
func _CFStringCreateWithCString(alloc _CFAllocatorRef, cstr []byte, encoding _CFStringEncoding) _CFStringRef {
ret, _, _ := purego.SyscallN(procCFStringCreateWithCString, uintptr(alloc), uintptr(unsafe.Pointer(&cstr[0])), uintptr(encoding))
return _CFStringRef(ret)
}

View File

@ -0,0 +1,185 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gamepad
import (
"unsafe"
"github.com/ebitengine/purego"
)
const kIOReturnSuccess = 0
const kIOHIDOptionsTypeNone _IOOptionBits = 0
const (
kIOHIDElementTypeInput_Misc = 1
kIOHIDElementTypeInput_Button = 2
kIOHIDElementTypeInput_Axis = 3
)
const (
kHIDPage_GenericDesktop = 0x1
kHIDPage_Simulation = 0x2
kHIDPage_Button = 0x9
kHIDPage_Consumer = 0x0C
)
const (
kHIDUsage_GD_Joystick = 0x4
kHIDUsage_GD_GamePad = 0x5
kHIDUsage_GD_MultiAxisController = 0x8
kHIDUsage_GD_X = 0x30
kHIDUsage_GD_Y = 0x31
kHIDUsage_GD_Z = 0x32
kHIDUsage_GD_Rx = 0x33
kHIDUsage_GD_Ry = 0x34
kHIDUsage_GD_Rz = 0x35
kHIDUsage_GD_Slider = 0x36
kHIDUsage_GD_Dial = 0x37
kHIDUsage_GD_Wheel = 0x38
kHIDUsage_GD_Hatswitch = 0x39
kHIDUsage_GD_Start = 0x3D
kHIDUsage_GD_Select = 0x3E
kHIDUsage_GD_SystemMainMenu = 0x85
kHIDUsage_GD_DPadUp = 0x90
kHIDUsage_GD_DPadDown = 0x91
kHIDUsage_GD_DPadRight = 0x92
kHIDUsage_GD_DPadLeft = 0x93
kHIDUsage_Sim_Rudder = 0xBA
kHIDUsage_Sim_Throttle = 0xBB
kHIDUsage_Sim_Accelerator = 0xC4
kHIDUsage_Sim_Brake = 0xC5
kHIDUsage_Sim_Steering = 0xC8
)
var (
kIOHIDVendorIDKey = []byte("VendorID\x00")
kIOHIDProductIDKey = []byte("ProductID\x00")
kIOHIDVersionNumberKey = []byte("VersionNumber\x00")
kIOHIDProductKey = []byte("Product\x00")
kIOHIDDeviceUsagePageKey = []byte("DeviceUsagePage\x00")
kIOHIDDeviceUsageKey = []byte("DeviceUsage\x00")
)
type _IOOptionBits uint32
type _IOHIDManagerRef uintptr
type _IOHIDDeviceRef uintptr
type _IOHIDElementRef uintptr
type _IOHIDValueRef uintptr
type _IOReturn int
type _IOHIDElementType uint
type _IOHIDDeviceCallback func(context unsafe.Pointer, result _IOReturn, sender unsafe.Pointer, device _IOHIDDeviceRef)
var (
iokit = purego.Dlopen("IOKit.framework/IOKit", purego.RTLD_GLOBAL)
procIOHIDElementGetTypeID = purego.Dlsym(iokit, "IOHIDElementGetTypeID")
procIOHIDManagerCreate = purego.Dlsym(iokit, "IOHIDManagerCreate")
procIOHIDDeviceGetProperty = purego.Dlsym(iokit, "IOHIDDeviceGetProperty")
procIOHIDManagerOpen = purego.Dlsym(iokit, "IOHIDManagerOpen")
procIOHIDManagerSetDeviceMatchingMultiple = purego.Dlsym(iokit, "IOHIDManagerSetDeviceMatchingMultiple")
procIOHIDManagerRegisterDeviceMatchingCallback = purego.Dlsym(iokit, "IOHIDManagerRegisterDeviceMatchingCallback")
procIOHIDManagerRegisterDeviceRemovalCallback = purego.Dlsym(iokit, "IOHIDManagerRegisterDeviceRemovalCallback")
procIOHIDManagerScheduleWithRunLoop = purego.Dlsym(iokit, "IOHIDManagerScheduleWithRunLoop")
procIOHIDElementGetType = purego.Dlsym(iokit, "IOHIDElementGetType")
procIOHIDElementGetUsage = purego.Dlsym(iokit, "IOHIDElementGetUsage")
procIOHIDElementGetUsagePage = purego.Dlsym(iokit, "IOHIDElementGetUsagePage")
procIOHIDElementGetLogicalMin = purego.Dlsym(iokit, "IOHIDElementGetLogicalMin")
procIOHIDElementGetLogicalMax = purego.Dlsym(iokit, "IOHIDElementGetLogicalMax")
procIOHIDDeviceGetValue = purego.Dlsym(iokit, "IOHIDDeviceGetValue")
procIOHIDValueGetIntegerValue = purego.Dlsym(iokit, "IOHIDValueGetIntegerValue")
procIOHIDDeviceCopyMatchingElements = purego.Dlsym(iokit, "IOHIDDeviceCopyMatchingElements")
)
func _IOHIDElementGetTypeID() _CFTypeID {
ret, _, _ := purego.SyscallN(procIOHIDElementGetTypeID)
return _CFTypeID(ret)
}
func _IOHIDManagerCreate(allocator _CFAllocatorRef, options _IOOptionBits) _IOHIDManagerRef {
ret, _, _ := purego.SyscallN(procIOHIDManagerCreate, uintptr(allocator), uintptr(options))
return _IOHIDManagerRef(ret)
}
func _IOHIDDeviceGetProperty(device _IOHIDDeviceRef, key _CFStringRef) _CFTypeRef {
ret, _, _ := purego.SyscallN(procIOHIDDeviceGetProperty, uintptr(device), uintptr(key))
return _CFTypeRef(ret)
}
func _IOHIDManagerOpen(manager _IOHIDManagerRef, options _IOOptionBits) _IOReturn {
ret, _, _ := purego.SyscallN(procIOHIDManagerOpen, uintptr(manager), uintptr(options))
return _IOReturn(ret)
}
func _IOHIDManagerSetDeviceMatchingMultiple(manager _IOHIDManagerRef, multiple _CFArrayRef) {
purego.SyscallN(procIOHIDManagerSetDeviceMatchingMultiple, uintptr(manager), uintptr(multiple))
}
func _IOHIDManagerRegisterDeviceMatchingCallback(manager _IOHIDManagerRef, callback _IOHIDDeviceCallback, context unsafe.Pointer) {
purego.SyscallN(procIOHIDManagerRegisterDeviceMatchingCallback, uintptr(manager), purego.NewCallback(callback), uintptr(context))
}
func _IOHIDManagerRegisterDeviceRemovalCallback(manager _IOHIDManagerRef, callback _IOHIDDeviceCallback, context unsafe.Pointer) {
purego.SyscallN(procIOHIDManagerRegisterDeviceRemovalCallback, uintptr(manager), purego.NewCallback(callback), uintptr(context))
}
func _IOHIDManagerScheduleWithRunLoop(manager _IOHIDManagerRef, runLoop _CFRunLoopRef, runLoopMode _CFStringRef) {
purego.SyscallN(procIOHIDManagerScheduleWithRunLoop, uintptr(manager), uintptr(runLoop), uintptr(runLoopMode))
}
func _IOHIDElementGetType(element _IOHIDElementRef) _IOHIDElementType {
ret, _, _ := purego.SyscallN(procIOHIDElementGetType, uintptr(element))
return _IOHIDElementType(ret)
}
func _IOHIDElementGetUsage(element _IOHIDElementRef) uint32 {
ret, _, _ := purego.SyscallN(procIOHIDElementGetUsage, uintptr(element))
return uint32(ret)
}
func _IOHIDElementGetUsagePage(element _IOHIDElementRef) uint32 {
ret, _, _ := purego.SyscallN(procIOHIDElementGetUsagePage, uintptr(element))
return uint32(ret)
}
func _IOHIDElementGetLogicalMin(element _IOHIDElementRef) _CFIndex {
ret, _, _ := purego.SyscallN(procIOHIDElementGetLogicalMin, uintptr(element))
return _CFIndex(ret)
}
func _IOHIDElementGetLogicalMax(element _IOHIDElementRef) _CFIndex {
ret, _, _ := purego.SyscallN(procIOHIDElementGetLogicalMax, uintptr(element))
return _CFIndex(ret)
}
func _IOHIDDeviceGetValue(device _IOHIDDeviceRef, element _IOHIDElementRef, pValue *_IOHIDValueRef) _IOReturn {
if pValue == nil {
panic("IOHID: pValue cannot be nil")
}
ret, _, _ := purego.SyscallN(procIOHIDDeviceGetValue, uintptr(device), uintptr(element), uintptr(unsafe.Pointer(pValue)))
return _IOReturn(ret)
}
func _IOHIDValueGetIntegerValue(value _IOHIDValueRef) _CFIndex {
ret, _, _ := purego.SyscallN(procIOHIDValueGetIntegerValue, uintptr(value))
return _CFIndex(ret)
}
func _IOHIDDeviceCopyMatchingElements(device _IOHIDDeviceRef, matching _CFDictionaryRef, options _IOOptionBits) _CFArrayRef {
ret, _, _ := purego.SyscallN(procIOHIDDeviceCopyMatchingElements, uintptr(device), uintptr(matching), uintptr(options))
return _CFArrayRef(ret)
}

View File

@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"sort"
"strings"
"sync"
"time"
"unsafe"
@ -28,43 +29,10 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
// #cgo LDFLAGS: -framework CoreFoundation -framework IOKit
//
// #include <ForceFeedback/ForceFeedback.h>
// #include <IOKit/hid/IOHIDLib.h>
//
// static CFStringRef cfStringRefIOHIDVendorIDKey() {
// return CFSTR(kIOHIDVendorIDKey);
// }
//
// static CFStringRef cfStringRefIOHIDProductIDKey() {
// return CFSTR(kIOHIDProductIDKey);
// }
//
// static CFStringRef cfStringRefIOHIDVersionNumberKey() {
// return CFSTR(kIOHIDVersionNumberKey);
// }
//
// static CFStringRef cfStringRefIOHIDProductKey() {
// return CFSTR(kIOHIDProductKey);
// }
//
// static CFStringRef cfStringRefIOHIDDeviceUsagePageKey() {
// return CFSTR(kIOHIDDeviceUsagePageKey);
// }
//
// static CFStringRef cfStringRefIOHIDDeviceUsageKey() {
// return CFSTR(kIOHIDDeviceUsageKey);
// }
//
// void ebitenGamepadMatchingCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef device);
// void ebitenGamepadRemovalCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef device);
import "C"
type nativeGamepadsImpl struct {
hidManager C.IOHIDManagerRef
devicesToAdd []C.IOHIDDeviceRef
devicesToRemove []C.IOHIDDeviceRef
hidManager _IOHIDManagerRef
devicesToAdd []_IOHIDDeviceRef
devicesToRemove []_IOHIDDeviceRef
devicesM sync.Mutex
}
@ -73,82 +41,80 @@ func newNativeGamepadsImpl() nativeGamepads {
}
func (g *nativeGamepadsImpl) init(gamepads *gamepads) error {
var dicts []C.CFDictionaryRef
var dicts []_CFDictionaryRef
page := C.kHIDPage_GenericDesktop
page := kHIDPage_GenericDesktop
for _, usage := range []uint{
C.kHIDUsage_GD_Joystick,
C.kHIDUsage_GD_GamePad,
C.kHIDUsage_GD_MultiAxisController,
kHIDUsage_GD_Joystick,
kHIDUsage_GD_GamePad,
kHIDUsage_GD_MultiAxisController,
} {
pageRef := C.CFNumberCreate(C.kCFAllocatorDefault, C.kCFNumberIntType, unsafe.Pointer(&page))
pageRef := _CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, unsafe.Pointer(&page))
if pageRef == 0 {
return errors.New("gamepad: CFNumberCreate returned nil")
}
defer C.CFRelease(C.CFTypeRef(pageRef))
defer _CFRelease(_CFTypeRef(pageRef))
usageRef := C.CFNumberCreate(C.kCFAllocatorDefault, C.kCFNumberIntType, unsafe.Pointer(&usage))
usageRef := _CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, unsafe.Pointer(&usage))
if usageRef == 0 {
return errors.New("gamepad: CFNumberCreate returned nil")
}
defer C.CFRelease(C.CFTypeRef(usageRef))
defer _CFRelease(_CFTypeRef(usageRef))
keys := []C.CFStringRef{
C.cfStringRefIOHIDDeviceUsagePageKey(),
C.cfStringRefIOHIDDeviceUsageKey(),
keys := []_CFStringRef{
_CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDDeviceUsagePageKey, kCFStringEncodingUTF8),
_CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDDeviceUsageKey, kCFStringEncodingUTF8),
}
values := []C.CFNumberRef{
values := []_CFNumberRef{
pageRef,
usageRef,
}
dict := C.CFDictionaryCreate(C.kCFAllocatorDefault,
dict := _CFDictionaryCreate(kCFAllocatorDefault,
(*unsafe.Pointer)(unsafe.Pointer(&keys[0])),
(*unsafe.Pointer)(unsafe.Pointer(&values[0])),
C.CFIndex(len(keys)), &C.kCFTypeDictionaryKeyCallBacks, &C.kCFTypeDictionaryValueCallBacks)
_CFIndex(len(keys)), *(**_CFDictionaryKeyCallBacks)(unsafe.Pointer(&kCFTypeDictionaryKeyCallBacks)), *(**_CFDictionaryValueCallBacks)(unsafe.Pointer(&kCFTypeDictionaryValueCallBacks)))
if dict == 0 {
return errors.New("gamepad: CFDictionaryCreate returned nil")
}
defer C.CFRelease(C.CFTypeRef(dict))
defer _CFRelease(_CFTypeRef(dict))
dicts = append(dicts, dict)
}
matching := C.CFArrayCreate(C.kCFAllocatorDefault,
matching := _CFArrayCreate(kCFAllocatorDefault,
(*unsafe.Pointer)(unsafe.Pointer(&dicts[0])),
C.CFIndex(len(dicts)), &C.kCFTypeArrayCallBacks)
_CFIndex(len(dicts)), *(**_CFArrayCallBacks)(unsafe.Pointer(&kCFTypeArrayCallBacks)))
if matching == 0 {
return errors.New("gamepad: CFArrayCreateMutable returned nil")
}
defer C.CFRelease(C.CFTypeRef(matching))
defer _CFRelease(_CFTypeRef(matching))
g.hidManager = C.IOHIDManagerCreate(C.kCFAllocatorDefault, C.kIOHIDOptionsTypeNone)
if C.IOHIDManagerOpen(g.hidManager, C.kIOHIDOptionsTypeNone) != C.kIOReturnSuccess {
g.hidManager = _IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone)
if _IOHIDManagerOpen(g.hidManager, kIOHIDOptionsTypeNone) != kIOReturnSuccess {
return errors.New("gamepad: IOHIDManagerOpen failed")
}
C.IOHIDManagerSetDeviceMatchingMultiple(g.hidManager, matching)
C.IOHIDManagerRegisterDeviceMatchingCallback(g.hidManager, C.IOHIDDeviceCallback(C.ebitenGamepadMatchingCallback), nil)
C.IOHIDManagerRegisterDeviceRemovalCallback(g.hidManager, C.IOHIDDeviceCallback(C.ebitenGamepadRemovalCallback), nil)
_IOHIDManagerSetDeviceMatchingMultiple(g.hidManager, matching)
_IOHIDManagerRegisterDeviceMatchingCallback(g.hidManager, ebitenGamepadMatchingCallback, nil)
_IOHIDManagerRegisterDeviceRemovalCallback(g.hidManager, ebitenGamepadRemovalCallback, nil)
C.IOHIDManagerScheduleWithRunLoop(g.hidManager, C.CFRunLoopGetMain(), C.kCFRunLoopDefaultMode)
_IOHIDManagerScheduleWithRunLoop(g.hidManager, _CFRunLoopGetMain(), **(**_CFStringRef)(unsafe.Pointer(&kCFRunLoopDefaultMode)))
// Execute the run loop once in order to register any initially-attached gamepads.
C.CFRunLoopRunInMode(C.kCFRunLoopDefaultMode, 0, 0 /* false */)
_CFRunLoopRunInMode(**(**_CFStringRef)(unsafe.Pointer(&kCFRunLoopDefaultMode)), 0, false)
return nil
}
//export ebitenGamepadMatchingCallback
func ebitenGamepadMatchingCallback(ctx unsafe.Pointer, res C.IOReturn, sender unsafe.Pointer, device C.IOHIDDeviceRef) {
func ebitenGamepadMatchingCallback(ctx unsafe.Pointer, res _IOReturn, sender unsafe.Pointer, device _IOHIDDeviceRef) {
n := theGamepads.native.(*nativeGamepadsImpl)
n.devicesM.Lock()
defer n.devicesM.Unlock()
n.devicesToAdd = append(n.devicesToAdd, device)
}
//export ebitenGamepadRemovalCallback
func ebitenGamepadRemovalCallback(ctx unsafe.Pointer, res C.IOReturn, sender unsafe.Pointer, device C.IOHIDDeviceRef) {
func ebitenGamepadRemovalCallback(ctx unsafe.Pointer, res _IOReturn, sender unsafe.Pointer, device _IOHIDDeviceRef) {
n := theGamepads.native.(*nativeGamepadsImpl)
n.devicesM.Lock()
defer n.devicesM.Unlock()
@ -173,7 +139,7 @@ func (g *nativeGamepadsImpl) update(gamepads *gamepads) error {
return nil
}
func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepads) {
func (g *nativeGamepadsImpl) addDevice(device _IOHIDDeviceRef, gamepads *gamepads) {
if gamepads.find(func(g *Gamepad) bool {
return g.native.(*nativeGamepadImpl).device == device
}) != nil {
@ -181,25 +147,25 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa
}
name := "Unknown"
if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDProductKey()); prop != 0 {
var cstr [256]C.char
C.CFStringGetCString(C.CFStringRef(prop), &cstr[0], C.CFIndex(len(cstr)), C.kCFStringEncodingUTF8)
name = C.GoString(&cstr[0])
if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDProductKey, kCFStringEncodingUTF8)); prop != 0 {
var cstr [256]byte
_CFStringGetCString(_CFStringRef(prop), cstr[:], kCFStringEncodingUTF8)
name = strings.TrimRight(string(cstr[:]), "\x00")
}
var vendor uint32
if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDVendorIDKey()); prop != 0 {
C.CFNumberGetValue(C.CFNumberRef(prop), C.kCFNumberSInt32Type, unsafe.Pointer(&vendor))
if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDVendorIDKey, kCFStringEncodingUTF8)); prop != 0 {
_CFNumberGetValue(_CFNumberRef(prop), kCFNumberSInt32Type, unsafe.Pointer(&vendor))
}
var product uint32
if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDProductIDKey()); prop != 0 {
C.CFNumberGetValue(C.CFNumberRef(prop), C.kCFNumberSInt32Type, unsafe.Pointer(&product))
if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDProductIDKey, kCFStringEncodingUTF8)); prop != 0 {
_CFNumberGetValue(_CFNumberRef(prop), kCFNumberSInt32Type, unsafe.Pointer(&product))
}
var version uint32
if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDVersionNumberKey()); prop != 0 {
C.CFNumberGetValue(C.CFNumberRef(prop), C.kCFNumberSInt32Type, unsafe.Pointer(&version))
if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDVersionNumberKey, kCFStringEncodingUTF8)); prop != 0 {
_CFNumberGetValue(_CFNumberRef(prop), kCFNumberSInt32Type, unsafe.Pointer(&version))
}
var sdlID string
@ -217,8 +183,8 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa
bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7], bs[8], bs[9], bs[10], bs[11])
}
elements := C.IOHIDDeviceCopyMatchingElements(device, 0, C.kIOHIDOptionsTypeNone)
defer C.CFRelease(C.CFTypeRef(elements))
elements := _IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone)
defer _CFRelease(_CFTypeRef(elements))
n := &nativeGamepadImpl{
device: device,
@ -226,71 +192,71 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa
gp := gamepads.add(name, sdlID)
gp.native = n
for i := C.CFIndex(0); i < C.CFArrayGetCount(elements); i++ {
native := (C.IOHIDElementRef)(C.CFArrayGetValueAtIndex(elements, i))
if C.CFGetTypeID(C.CFTypeRef(native)) != C.IOHIDElementGetTypeID() {
for i := _CFIndex(0); i < _CFArrayGetCount(_CFArrayRef(elements)); i++ {
native := (_IOHIDElementRef)(_CFArrayGetValueAtIndex(_CFArrayRef(elements), i))
if _CFGetTypeID(_CFTypeRef(native)) != _IOHIDElementGetTypeID() {
continue
}
typ := C.IOHIDElementGetType(native)
if typ != C.kIOHIDElementTypeInput_Axis &&
typ != C.kIOHIDElementTypeInput_Button &&
typ != C.kIOHIDElementTypeInput_Misc {
typ := _IOHIDElementGetType(native)
if typ != kIOHIDElementTypeInput_Axis &&
typ != kIOHIDElementTypeInput_Button &&
typ != kIOHIDElementTypeInput_Misc {
continue
}
usage := C.IOHIDElementGetUsage(native)
page := C.IOHIDElementGetUsagePage(native)
usage := _IOHIDElementGetUsage(native)
page := _IOHIDElementGetUsagePage(native)
switch page {
case C.kHIDPage_GenericDesktop:
case kHIDPage_GenericDesktop:
switch usage {
case C.kHIDUsage_GD_X, C.kHIDUsage_GD_Y, C.kHIDUsage_GD_Z,
C.kHIDUsage_GD_Rx, C.kHIDUsage_GD_Ry, C.kHIDUsage_GD_Rz,
C.kHIDUsage_GD_Slider, C.kHIDUsage_GD_Dial, C.kHIDUsage_GD_Wheel:
case kHIDUsage_GD_X, kHIDUsage_GD_Y, kHIDUsage_GD_Z,
kHIDUsage_GD_Rx, kHIDUsage_GD_Ry, kHIDUsage_GD_Rz,
kHIDUsage_GD_Slider, kHIDUsage_GD_Dial, kHIDUsage_GD_Wheel:
n.axes = append(n.axes, element{
native: native,
usage: int(usage),
index: len(n.axes),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
minimum: int(_IOHIDElementGetLogicalMin(native)),
maximum: int(_IOHIDElementGetLogicalMax(native)),
})
case C.kHIDUsage_GD_Hatswitch:
case kHIDUsage_GD_Hatswitch:
n.hats = append(n.hats, element{
native: native,
usage: int(usage),
index: len(n.hats),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
minimum: int(_IOHIDElementGetLogicalMin(native)),
maximum: int(_IOHIDElementGetLogicalMax(native)),
})
case C.kHIDUsage_GD_DPadUp, C.kHIDUsage_GD_DPadRight, C.kHIDUsage_GD_DPadDown, C.kHIDUsage_GD_DPadLeft,
C.kHIDUsage_GD_SystemMainMenu, C.kHIDUsage_GD_Select, C.kHIDUsage_GD_Start:
case kHIDUsage_GD_DPadUp, kHIDUsage_GD_DPadRight, kHIDUsage_GD_DPadDown, kHIDUsage_GD_DPadLeft,
kHIDUsage_GD_SystemMainMenu, kHIDUsage_GD_Select, kHIDUsage_GD_Start:
n.buttons = append(n.buttons, element{
native: native,
usage: int(usage),
index: len(n.buttons),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
minimum: int(_IOHIDElementGetLogicalMin(native)),
maximum: int(_IOHIDElementGetLogicalMax(native)),
})
}
case C.kHIDPage_Simulation:
case kHIDPage_Simulation:
switch usage {
case C.kHIDUsage_Sim_Accelerator, C.kHIDUsage_Sim_Brake, C.kHIDUsage_Sim_Throttle, C.kHIDUsage_Sim_Rudder, C.kHIDUsage_Sim_Steering:
case kHIDUsage_Sim_Accelerator, kHIDUsage_Sim_Brake, kHIDUsage_Sim_Throttle, kHIDUsage_Sim_Rudder, kHIDUsage_Sim_Steering:
n.axes = append(n.axes, element{
native: native,
usage: int(usage),
index: len(n.axes),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
minimum: int(_IOHIDElementGetLogicalMin(native)),
maximum: int(_IOHIDElementGetLogicalMax(native)),
})
}
case C.kHIDPage_Button, C.kHIDPage_Consumer:
case kHIDPage_Button, kHIDPage_Consumer:
n.buttons = append(n.buttons, element{
native: native,
usage: int(usage),
index: len(n.buttons),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
minimum: int(_IOHIDElementGetLogicalMin(native)),
maximum: int(_IOHIDElementGetLogicalMax(native)),
})
}
}
@ -301,7 +267,7 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa
}
type element struct {
native C.IOHIDElementRef
native _IOHIDElementRef
usage int
index int
minimum int
@ -329,7 +295,7 @@ func (e elements) Swap(i, j int) {
}
type nativeGamepadImpl struct {
device C.IOHIDDeviceRef
device _IOHIDDeviceRef
axes elements
buttons elements
hats elements
@ -340,11 +306,10 @@ type nativeGamepadImpl struct {
}
func (g *nativeGamepadImpl) elementValue(e *element) int {
var valueRef C.IOHIDValueRef
if C.IOHIDDeviceGetValue(g.device, e.native, &valueRef) == C.kIOReturnSuccess {
return int(C.IOHIDValueGetIntegerValue(valueRef))
var valueRef _IOHIDValueRef
if _IOHIDDeviceGetValue(g.device, e.native, &valueRef) == kIOReturnSuccess {
return int(_IOHIDValueGetIntegerValue(valueRef))
}
return 0
}