Compare commits
No commits in common. "main" and "0.2.0" have entirely different histories.
166
.clang-format
166
.clang-format
|
@ -1,166 +0,0 @@
|
||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
# BasedOnStyle: LLVM
|
|
||||||
AccessModifierOffset: -2
|
|
||||||
AlignAfterOpenBracket: AlwaysBreak
|
|
||||||
AlignConsecutiveMacros: None
|
|
||||||
AlignConsecutiveAssignments: None
|
|
||||||
AlignConsecutiveBitFields: None
|
|
||||||
AlignConsecutiveDeclarations: None
|
|
||||||
AlignEscapedNewlines: Right
|
|
||||||
AlignOperands: Align
|
|
||||||
AlignTrailingComments: true
|
|
||||||
AllowAllArgumentsOnNextLine: false
|
|
||||||
AllowAllConstructorInitializersOnNextLine: true
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
|
||||||
AllowShortEnumsOnASingleLine: true
|
|
||||||
AllowShortBlocksOnASingleLine: Never
|
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
|
||||||
AllowShortFunctionsOnASingleLine: All
|
|
||||||
AllowShortLambdasOnASingleLine: All
|
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
AlwaysBreakAfterReturnType: None
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
AlwaysBreakTemplateDeclarations: MultiLine
|
|
||||||
AttributeMacros:
|
|
||||||
- __capability
|
|
||||||
BinPackArguments: false
|
|
||||||
BinPackParameters: false
|
|
||||||
BraceWrapping:
|
|
||||||
AfterCaseLabel: false
|
|
||||||
AfterClass: false
|
|
||||||
AfterControlStatement: Never
|
|
||||||
AfterEnum: false
|
|
||||||
AfterFunction: false
|
|
||||||
AfterNamespace: false
|
|
||||||
AfterObjCDeclaration: false
|
|
||||||
AfterStruct: false
|
|
||||||
AfterUnion: false
|
|
||||||
AfterExternBlock: false
|
|
||||||
BeforeCatch: false
|
|
||||||
BeforeElse: false
|
|
||||||
BeforeLambdaBody: false
|
|
||||||
BeforeWhile: false
|
|
||||||
IndentBraces: false
|
|
||||||
SplitEmptyFunction: true
|
|
||||||
SplitEmptyRecord: true
|
|
||||||
SplitEmptyNamespace: true
|
|
||||||
BreakBeforeBinaryOperators: None
|
|
||||||
BreakBeforeConceptDeclarations: true
|
|
||||||
BreakBeforeBraces: Allman
|
|
||||||
BreakBeforeInheritanceComma: false
|
|
||||||
BreakInheritanceList: BeforeColon
|
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializersBeforeComma: false
|
|
||||||
BreakConstructorInitializers: BeforeColon
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
|
||||||
BreakStringLiterals: true
|
|
||||||
ColumnLimit: 100
|
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
|
||||||
CompactNamespaces: false
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
ConstructorInitializerIndentWidth: 4
|
|
||||||
ContinuationIndentWidth: 4
|
|
||||||
Cpp11BracedListStyle: true
|
|
||||||
DeriveLineEnding: true
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
DisableFormat: false
|
|
||||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
FixNamespaceComments: true
|
|
||||||
ForEachMacros:
|
|
||||||
- foreach
|
|
||||||
- Q_FOREACH
|
|
||||||
- BOOST_FOREACH
|
|
||||||
StatementAttributeLikeMacros:
|
|
||||||
- Q_EMIT
|
|
||||||
IncludeBlocks: Preserve
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
|
||||||
Priority: 2
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
|
||||||
Priority: 3
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: '.*'
|
|
||||||
Priority: 1
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
IncludeIsMainRegex: '(Test)?$'
|
|
||||||
IncludeIsMainSourceRegex: ''
|
|
||||||
IndentCaseLabels: false
|
|
||||||
IndentCaseBlocks: false
|
|
||||||
IndentGotoLabels: true
|
|
||||||
IndentPPDirectives: None
|
|
||||||
IndentExternBlock: NoIndent
|
|
||||||
IndentRequires: false
|
|
||||||
IndentWidth: 4
|
|
||||||
IndentWrappedFunctionNames: false
|
|
||||||
InsertTrailingCommas: None
|
|
||||||
JavaScriptQuotes: Leave
|
|
||||||
JavaScriptWrapImports: true
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
|
||||||
MacroBlockBegin: ''
|
|
||||||
MacroBlockEnd: ''
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
NamespaceIndentation: None
|
|
||||||
ObjCBinPackProtocolList: Auto
|
|
||||||
ObjCBlockIndentWidth: 4
|
|
||||||
ObjCBreakBeforeNestedBlockParam: true
|
|
||||||
ObjCSpaceAfterProperty: false
|
|
||||||
ObjCSpaceBeforeProtocolList: true
|
|
||||||
PenaltyBreakAssignment: 2
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 19
|
|
||||||
PenaltyBreakComment: 300
|
|
||||||
PenaltyBreakFirstLessLess: 120
|
|
||||||
PenaltyBreakString: 1000
|
|
||||||
PenaltyBreakTemplateDeclaration: 10
|
|
||||||
PenaltyExcessCharacter: 1000000
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 1000000
|
|
||||||
PenaltyIndentedWhitespace: 0
|
|
||||||
PointerAlignment: Right
|
|
||||||
ReflowComments: true
|
|
||||||
SortIncludes: true
|
|
||||||
SortJavaStaticImport: Before
|
|
||||||
SortUsingDeclarations: true
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceAfterLogicalNot: false
|
|
||||||
SpaceAfterTemplateKeyword: true
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
SpaceBeforeCaseColon: false
|
|
||||||
SpaceBeforeCpp11BracedList: false
|
|
||||||
SpaceBeforeCtorInitializerColon: true
|
|
||||||
SpaceBeforeInheritanceColon: true
|
|
||||||
SpaceBeforeParens: ControlStatements
|
|
||||||
SpaceAroundPointerQualifiers: Default
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
|
||||||
SpaceInEmptyBlock: false
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInConditionalStatement: false
|
|
||||||
SpacesInContainerLiterals: true
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
SpaceBeforeSquareBrackets: false
|
|
||||||
BitFieldColonSpacing: Both
|
|
||||||
Standard: Latest
|
|
||||||
StatementMacros:
|
|
||||||
- Q_UNUSED
|
|
||||||
- QT_REQUIRE_VERSION
|
|
||||||
TabWidth: 8
|
|
||||||
UseCRLF: false
|
|
||||||
UseTab: Never
|
|
||||||
WhitespaceSensitiveMacros:
|
|
||||||
- STRINGIZE
|
|
||||||
- PP_STRINGIZE
|
|
||||||
- BOOST_PP_STRINGIZE
|
|
||||||
- NS_SWIFT_NAME
|
|
||||||
- CF_SWIFT_NAME
|
|
||||||
...
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.so filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.so.0 filter=lfs diff=lfs merge=lfs -text
|
|
|
@ -1,5 +1,3 @@
|
||||||
.vscode
|
.vscode
|
||||||
.vs
|
.vs
|
||||||
visualc/x64
|
visualc/x64
|
||||||
build/
|
|
||||||
android/buildandroid/
|
|
||||||
|
|
143
CMakeLists.txt
143
CMakeLists.txt
|
@ -1,143 +0,0 @@
|
||||||
# CMake Project for FAudioGMS
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
|
||||||
project(FAudioGMS C)
|
|
||||||
|
|
||||||
#Options
|
|
||||||
option(BUILD_SHARED_LIBS "Build shared library" ON)
|
|
||||||
|
|
||||||
SET(LIB_MAJOR_VERSION "0")
|
|
||||||
SET(LIB_MINOR_VERSION "2")
|
|
||||||
SET(LIB_REVISION "0")
|
|
||||||
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}")
|
|
||||||
|
|
||||||
# Build Type
|
|
||||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
||||||
# By default, we use Release
|
|
||||||
message(STATUS "Setting build type to 'Release' as none was specified.")
|
|
||||||
set(CMAKE_BUILD_TYPE "Release" CACHE
|
|
||||||
STRING "Choose the type of build." FORCE
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set the possible values of build type for cmake-gui
|
|
||||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
|
|
||||||
STRINGS "Debug" "Release" "RelWithDebInfo"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Platform Flags
|
|
||||||
if(APPLE)
|
|
||||||
set(CMAKE_MACOSX_RPATH ON)
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
|
||||||
set(LOBJC "objc")
|
|
||||||
elseif(WIN32)
|
|
||||||
# "FAudioGMS.dll", not "libFAudioGMS.dll"
|
|
||||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
SET(BIN_RPATH "\$ORIGIN;\$ORIGIN/assets") #thanks yoyo games
|
|
||||||
set(CMAKE_SKIP_BUILD_RPATH TRUE)
|
|
||||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
|
||||||
set(CMAKE_INSTALL_RPATH ${BIN_RPATH})
|
|
||||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Source lists
|
|
||||||
add_library(FAudioGMS
|
|
||||||
#Public header
|
|
||||||
src/FAudioGMS.h
|
|
||||||
#Source files
|
|
||||||
lib/dr_wav.h
|
|
||||||
src/FAudioGMS.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# FAudio Source lists
|
|
||||||
add_library(FAudio STATIC
|
|
||||||
# Public Headers
|
|
||||||
lib/FAudio/include/F3DAudio.h
|
|
||||||
lib/FAudio/include/FACT3D.h
|
|
||||||
lib/FAudio/include/FACT.h
|
|
||||||
lib/FAudio/include/FAPOBase.h
|
|
||||||
lib/FAudio/include/FAPOFX.h
|
|
||||||
lib/FAudio/include/FAPO.h
|
|
||||||
lib/FAudio/include/FAudioFX.h
|
|
||||||
lib/FAudio/include/FAudio.h
|
|
||||||
# Internal Headers
|
|
||||||
lib/FAudio/src/FACT_internal.h
|
|
||||||
lib/FAudio/src/FAudio_internal.h
|
|
||||||
lib/FAudio/src/stb.h
|
|
||||||
lib/FAudio/src/stb_vorbis.h
|
|
||||||
# Source Files
|
|
||||||
lib/FAudio/src/F3DAudio.c
|
|
||||||
lib/FAudio/src/FACT3D.c
|
|
||||||
lib/FAudio/src/FACT.c
|
|
||||||
lib/FAudio/src/FACT_internal.c
|
|
||||||
lib/FAudio/src/FAPOBase.c
|
|
||||||
lib/FAudio/src/FAPOFX.c
|
|
||||||
lib/FAudio/src/FAPOFX_echo.c
|
|
||||||
lib/FAudio/src/FAPOFX_eq.c
|
|
||||||
lib/FAudio/src/FAPOFX_masteringlimiter.c
|
|
||||||
lib/FAudio/src/FAPOFX_reverb.c
|
|
||||||
lib/FAudio/src/FAudio.c
|
|
||||||
lib/FAudio/src/FAudioFX_reverb.c
|
|
||||||
lib/FAudio/src/FAudioFX_volumemeter.c
|
|
||||||
lib/FAudio/src/FAudio_internal.c
|
|
||||||
lib/FAudio/src/FAudio_internal_simd.c
|
|
||||||
lib/FAudio/src/FAudio_operationset.c
|
|
||||||
lib/FAudio/src/FAudio_platform_sdl2.c
|
|
||||||
lib/FAudio/src/FAudio_platform_win32.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Build flags
|
|
||||||
if(NOT MSVC)
|
|
||||||
set_property(TARGET FAudioGMS PROPERTY COMPILE_FLAGS "-std=gnu99 -Wall -Wno-strict-aliasing -pedantic")
|
|
||||||
set_property(TARGET FAudio PROPERTY COMPILE_FLAGS "-fPIC")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# includes
|
|
||||||
target_include_directories(FAudioGMS PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib/FAudio/include>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib/SDL/include>
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(FAudio PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib/FAudio/include>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib/SDL/include>
|
|
||||||
)
|
|
||||||
|
|
||||||
# Soname
|
|
||||||
set_target_properties(FAudioGMS PROPERTIES OUTPUT_NAME "FAudioGMS"
|
|
||||||
VERSION ${LIB_VERSION}
|
|
||||||
SOVERSION ${LIB_MAJOR_VERSION}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Internal Dependencies
|
|
||||||
target_link_libraries(FAudioGMS PRIVATE FAudio ${LOBJC})
|
|
||||||
|
|
||||||
# SDL2 Dependency
|
|
||||||
if (DEFINED SDL2_INCLUDE_DIRS AND DEFINED SDL2_LIBRARIES)
|
|
||||||
message(STATUS "using pre-defined SDL2 variables SDL2_INCLUDE_DIRS and SDL2_LIBRARIES")
|
|
||||||
target_include_directories(FAudioGMS PUBLIC "$<BUILD_INTERFACE:${SDL2_INCLUDE_DIRS}>")
|
|
||||||
target_include_directories(FAudio PUBLIC "$<BUILD_INTERFACE:${SDL2_INCLUDE_DIRS}>")
|
|
||||||
target_link_libraries(FAudioGMS PUBLIC ${SDL2_LIBRARIES})
|
|
||||||
else()
|
|
||||||
# Only try to autodetect if both SDL2 variables aren't explicitly set
|
|
||||||
find_package(SDL2 CONFIG)
|
|
||||||
if (TARGET SDL2::SDL2)
|
|
||||||
message(STATUS "using TARGET SDL2::SDL2")
|
|
||||||
target_link_libraries(FAudioGMS PUBLIC SDL2::SDL2)
|
|
||||||
target_link_libraries(FAudio PUBLIC SDL2::SDL2)
|
|
||||||
elseif (TARGET SDL2)
|
|
||||||
message(STATUS "using TARGET SDL2")
|
|
||||||
target_link_libraries(FAudioGMS PUBLIC SDL2)
|
|
||||||
target_link_libraries(FAudio PUBLIC SDL2)
|
|
||||||
else()
|
|
||||||
message(STATUS "no TARGET SDL2::SDL2, or SDL2, using variables")
|
|
||||||
target_include_directories(FAudioGMS PUBLIC "$<BUILD_INTERFACE:${SDL2_INCLUDE_DIRS}>")
|
|
||||||
target_include_directories(FAudio PUBLIC "$<BUILD_INTERFACE:${SDL2_INCLUDE_DIRS}>")
|
|
||||||
target_link_libraries(FAudioGMS PUBLIC ${SDL2_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
46
README.md
46
README.md
|
@ -10,63 +10,21 @@ FAudioGMS can leak memory if used improperly, so keep track of your sound instan
|
||||||
|
|
||||||
As a final addendum, if the YoYo Games circus needs a new clown for tasks like fixing the audio engine that's been mostly broken for a decade, I am a highly skilled programmer and I work for competitive rates. You know where to find me.
|
As a final addendum, if the YoYo Games circus needs a new clown for tasks like fixing the audio engine that's been mostly broken for a decade, I am a highly skilled programmer and I work for competitive rates. You know where to find me.
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
If you are on Windows, make SURE "Use x64 Windows runtime" is checked under Game Options -> Windows!
|
|
||||||
|
|
||||||
Place your audio files in Included Files. The `.yymps` has an example structure.
|
|
||||||
|
|
||||||
Make sure the `AUDIO` object is created once at the start of your game.
|
|
||||||
|
|
||||||
You can use the documented wrapper functions included in the `.yymps` to control audio,
|
|
||||||
or you can just use the C API directly and wrap it yourself.
|
|
||||||
|
|
||||||
Detailed API documentation can be found [here](http://moonside.games/docs/FAudioGMS/#/latest/).
|
|
||||||
|
|
||||||
## Platforms
|
## Platforms
|
||||||
|
|
||||||
FAudio itself is cross-platform and has been deployed by hundreds of games across many platforms.
|
|
||||||
FAudioGMS intends to support all the platforms that FAudio does,
|
|
||||||
but I need to get around to personally building and testing it for these platforms.
|
|
||||||
I will not be supporting 32-bit Windows. Catch up to 2004 and switch to 64-bit.
|
|
||||||
|
|
||||||
### Tested
|
### Tested
|
||||||
- Windows (64-bit)
|
- Windows
|
||||||
- Linux
|
|
||||||
- Android (I will not help you if it breaks, sorry, Android sucks, ask Nik if you need help)
|
|
||||||
|
|
||||||
### Theoretical
|
### Theoretical
|
||||||
- OSX
|
- OSX
|
||||||
|
- Linux
|
||||||
- Nintendo Switch
|
- Nintendo Switch
|
||||||
- Xbox One
|
|
||||||
- iOS
|
- iOS
|
||||||
|
|
||||||
### Not Supported
|
|
||||||
- Windows (32-bit)
|
|
||||||
- HTML5 (if someone wants to try this go ahead but I'm not touching that garbage with a 10 foot pole)
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
FAudioGMS depends on FAudio (obviously) and SDL2. We avoid directly depending on the C runtime.
|
FAudioGMS depends on FAudio (obviously) and SDL2. We avoid directly depending on the C runtime.
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
Open the project contained in the `visualc` directory in Visual Studio and build.
|
|
||||||
|
|
||||||
### OSX/Linux
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=/usr/bin/clang -S . -B ./build
|
|
||||||
cd ./build
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
### Console Platforms
|
|
||||||
|
|
||||||
You will need to show proof of NDA to obtain SDL source for your platform.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This library is licensed under the zlib license. See LICENSE file for details.
|
This library is licensed under the zlib license. See LICENSE file for details.
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
# FAudioGMS Android.mk file
|
|
||||||
# PS: Expect hell
|
|
||||||
|
|
||||||
SAVED_LOCAL_PATH := $(call my-dir)
|
|
||||||
LOCAL_PATH := $(SAVED_LOCAL_PATH)
|
|
||||||
SDL_PATH := $(LOCAL_PATH)/../lib/SDL
|
|
||||||
FAUDIO_PATH := $(LOCAL_PATH)/../lib/FAudio
|
|
||||||
FAUDIOGMS_PATH := $(LOCAL_PATH)/..
|
|
||||||
|
|
||||||
# First we import SDL 2
|
|
||||||
|
|
||||||
include $(SDL_PATH)/Android.mk
|
|
||||||
|
|
||||||
# Then we compile FAudio as a static library
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(SAVED_LOCAL_PATH)
|
|
||||||
LOCAL_MODULE := FAudio_static
|
|
||||||
LOCAL_MODULE_FILENAME := libFAudio
|
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := SDL2
|
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := $(SDL_PATH)/include $(FAUDIO_PATH)/include $(FAUDIO_PATH)/src
|
|
||||||
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
|
||||||
|
|
||||||
LOCAL_LDLIBS :=
|
|
||||||
|
|
||||||
LOCAL_EXPORT_LDLIBS := -ldl -llog -landroid
|
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
|
||||||
$(FAUDIO_PATH)/src/F3DAudio.c \
|
|
||||||
$(FAUDIO_PATH)/src/FACT3D.c \
|
|
||||||
$(FAUDIO_PATH)/src/FACT.c \
|
|
||||||
$(FAUDIO_PATH)/src/FACT_internal.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAPOBase.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAPOFX.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAPOFX_echo.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAPOFX_eq.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAPOFX_masteringlimiter.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAPOFX_reverb.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudio.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudioFX_reverb.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudioFX_volumemeter.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudio_internal.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudio_internal_simd.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudio_operationset.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudio_platform_sdl2.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudio_platform_win32.c \
|
|
||||||
$(FAUDIO_PATH)/src/XNA_Song.c \
|
|
||||||
$(FAUDIO_PATH)/src/FAudio_gstreamer.c
|
|
||||||
|
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
# And then we do our stuff...
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(SAVED_LOCAL_PATH)
|
|
||||||
|
|
||||||
LOCAL_MODULE := FAudioGMS
|
|
||||||
# Tell ndk-build we rely on these two fellas:
|
|
||||||
LOCAL_SHARED_LIBRARIES := SDL2 FAudio_static
|
|
||||||
LOCAL_C_INCLUDES := $(SDL_PATH)/include $(FAUDIO_PATH)/include $(FAUDIOGMS_PATH)/src
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
|
||||||
LOCAL_SRC_FILES := $(FAUDIOGMS_PATH)/src/FAudioGMS.c $(LOCAL_PATH)/FAudioGMS_JNI.c
|
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
|
@ -1,468 +0,0 @@
|
||||||
/* FAudioGMS - Game Maker FAudio bindings in C
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021 Evan Hemsley
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied warranty.
|
|
||||||
* In no event will the authors be held liable for any damages arising from
|
|
||||||
* the use of this software.
|
|
||||||
*
|
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
|
||||||
* including commercial applications, and to alter it and redistribute it
|
|
||||||
* freely, subject to the following restrictions:
|
|
||||||
*
|
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
* claim that you wrote the original software. If you use this software in a
|
|
||||||
* product, an acknowledgment in the product documentation would be
|
|
||||||
* appreciated but is not required.
|
|
||||||
*
|
|
||||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
* misrepresented as being the original software.
|
|
||||||
*
|
|
||||||
* 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*
|
|
||||||
* Evan "cosmonaut" Hemsley <evan@moonside.games>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* These are the Native -> JNI conv wrappers, they must only be built for Android */
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
|
|
||||||
/* no mangling please */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include <FAudioGMS.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1Init
|
|
||||||
|
|
||||||
JNIEXPORT: export this function for JNI
|
|
||||||
jdouble: return type, a GameMaker function must always return something
|
|
||||||
JNICALL: JNI calling convention
|
|
||||||
|
|
||||||
Java_class_path_here_classNameHere_Function_Name_Here
|
|
||||||
|
|
||||||
classpath: org.screwyoyo.faudiogms
|
|
||||||
classname: FAudioGMSNative
|
|
||||||
function name: FAudioGMSNative_FAudioGMS_1Init
|
|
||||||
|
|
||||||
underscores must be escaped with _1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* replace this with -1.0 or NAN if you wish... */
|
|
||||||
/* ideally, a jdouble should map to a double */
|
|
||||||
#define NOTHING ((jdouble)0.0)
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1Init
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _spatialDistanceScale, jdouble _timestep)
|
|
||||||
{
|
|
||||||
FAudioGMS_Init(_spatialDistanceScale, _timestep);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1StaticSound_1LoadWAV
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jstring _filePath)
|
|
||||||
{
|
|
||||||
jboolean isCopy;
|
|
||||||
const char* filePath;
|
|
||||||
jdouble ret;
|
|
||||||
|
|
||||||
filePath = (*jniEnv)->GetStringUTFChars(jniEnv, _filePath, &isCopy);
|
|
||||||
ret = FAudioGMS_StaticSound_LoadWAV((char *)filePath);
|
|
||||||
(*jniEnv)->ReleaseStringUTFChars(jniEnv, _filePath, filePath);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1StaticSound_1CreateSoundInstance
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _staticSoundID)
|
|
||||||
{
|
|
||||||
return (jdouble)FAudioGMS_StaticSound_CreateSoundInstance(_staticSoundID);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1StaticSound_1Destroy
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _staticSoundID)
|
|
||||||
{
|
|
||||||
FAudioGMS_StaticSound_Destroy(_staticSoundID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1StreamingSound_1LoadOGG
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jstring _filepath, jdouble _bufferSizeInBytes)
|
|
||||||
{
|
|
||||||
jboolean isCopy;
|
|
||||||
const char* filepath;
|
|
||||||
jdouble ret;
|
|
||||||
|
|
||||||
filepath = (*jniEnv)->GetStringUTFChars(jniEnv, _filepath, &isCopy);
|
|
||||||
ret = FAudioGMS_StreamingSound_LoadOGG((char *)filepath, _bufferSizeInBytes);
|
|
||||||
(*jniEnv)->ReleaseStringUTFChars(jniEnv, _filepath, filepath);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1Play
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Play(_soundInstanceID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1Pause
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Pause(_soundInstanceID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1Stop
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Stop(_soundInstanceID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1QueueSyncPlay
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_QueueSyncPlay(_soundInstanceID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SyncPlay
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SyncPlay();
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetPlayRegion
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _startInMilliseconds, jdouble _endInMilliseconds)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetPlayRegion(_soundInstanceID, _startInMilliseconds, _endInMilliseconds);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetLoop
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _loop)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetLoop(_soundInstanceID, _loop);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetPan
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _pan)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetPan(_soundInstanceID, _pan);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetPitch
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _pitch)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetPitch(_soundInstanceID, _pitch);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetVolume
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _volume)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetVolume(_soundInstanceID, _volume);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1Set3DPosition
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _x, jdouble _y, jdouble _z)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Set3DPosition(_soundInstanceID, _x, _y, _z);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1Set3DVelocity
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _xVelocity, jdouble _yVelocity, jdouble _zVelocity)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Set3DVelocity(_soundInstanceID, _xVelocity, _yVelocity, _zVelocity);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1Set3DOrientation
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _xFront, jdouble _yFront, jdouble _zFront, jdouble _xTop, jdouble _yTop, jdouble _zTop)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Set3DOrientation(_soundInstanceID, _xFront, _yFront, _zFront, _xTop, _yTop, _zTop);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetTrackPositionInSeconds
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _trackPositionInSeconds)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetTrackPositionInSeconds(_soundInstanceID, _trackPositionInSeconds);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetVolumeOverTime
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _volume, jdouble _milliseconds)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetVolumeOverTime(_soundInstanceID, _volume, _milliseconds);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetLowPassFilter
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _lowPassFilter, jdouble _Q)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetLowPassFilter(_soundInstanceID, _lowPassFilter, _Q);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetHighPassFilter
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _highPassFilter, jdouble _Q)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetHighPassFilter(_soundInstanceID, _highPassFilter, _Q);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetBandPassFilter
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _bandPassFilter, jdouble _Q)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetBandPassFilter(_soundInstanceID, _bandPassFilter, _Q);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1QueueSoundInstance
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _queueSoundInstanceID)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_QueueSoundInstance(_soundInstanceID, _queueSoundInstanceID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1GetPitch
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
return (jdouble)FAudioGMS_SoundInstance_GetPitch(_soundInstanceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1GetVolume
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
return (jdouble)FAudioGMS_SoundInstance_GetVolume(_soundInstanceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1GetTrackLengthInSeconds
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
return (jdouble)FAudioGMS_SoundInstance_GetTrackLengthInSeconds(_soundInstanceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1GetTrackPositionInSeconds
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
return (jdouble)FAudioGMS_SoundInstance_GetTrackPositionInSeconds(_soundInstanceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1Destroy
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Destroy(_soundInstanceID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1DestroyWhenFinished
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_DestroyWhenFinished(_soundInstanceID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1EffectChain_1Create
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis)
|
|
||||||
{
|
|
||||||
return (jdouble)FAudioGMS_EffectChain_Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1EffectChain_1AddDefaultReverb
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _effectChainID)
|
|
||||||
{
|
|
||||||
FAudioGMS_EffectChain_AddDefaultReverb(_effectChainID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1EffectChain_1AddReverb
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis,
|
|
||||||
jdouble _effectChainID,
|
|
||||||
jdouble _wetDryMix,
|
|
||||||
jdouble _reflectionsDelay,
|
|
||||||
jdouble _reverbDelay,
|
|
||||||
jdouble _earlyDiffusion,
|
|
||||||
jdouble _lateDiffusion,
|
|
||||||
jdouble _lowEQGain,
|
|
||||||
jdouble _lowEQCutoff,
|
|
||||||
jdouble _highEQGain,
|
|
||||||
jdouble _highEQCutoff,
|
|
||||||
jdouble _reflectionsGain,
|
|
||||||
jdouble _reverbGain,
|
|
||||||
jdouble _decayTime,
|
|
||||||
jdouble _density,
|
|
||||||
jdouble _roomSize)
|
|
||||||
{
|
|
||||||
FAudioGMS_EffectChain_AddReverb(
|
|
||||||
_effectChainID,
|
|
||||||
_wetDryMix,
|
|
||||||
_reflectionsDelay,
|
|
||||||
_reverbDelay,
|
|
||||||
_earlyDiffusion,
|
|
||||||
_lateDiffusion,
|
|
||||||
_lowEQGain,
|
|
||||||
_lowEQCutoff,
|
|
||||||
_highEQGain,
|
|
||||||
_highEQCutoff,
|
|
||||||
_reflectionsGain,
|
|
||||||
_reverbGain,
|
|
||||||
_decayTime,
|
|
||||||
_density,
|
|
||||||
_roomSize);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1EffectChain_1Destroy
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _effectChainID)
|
|
||||||
{
|
|
||||||
FAudioGMS_EffectChain_Destroy(_effectChainID);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetEffectChain
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _effectChainID, jdouble _effectGain)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetEffectChain(_soundInstanceID, _effectChainID, _effectGain);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SoundInstance_1SetEffectGain
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _soundInstanceID, jdouble _effectGain)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetEffectGain(_soundInstanceID, _effectGain);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SetMasteringEffectChain
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _effectChainID, double _effectGain)
|
|
||||||
{
|
|
||||||
FAudioGMS_SetMasteringEffectChain(_effectChainID, _effectGain);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SetMasteringEffectGain
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _effectGain)
|
|
||||||
{
|
|
||||||
FAudioGMS_SetMasteringEffectGain(_effectGain);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SetListenerPosition
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _x, jdouble _y, jdouble _z)
|
|
||||||
{
|
|
||||||
FAudioGMS_SetListenerPosition(_x, _y, _z);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SetListenerVelocity
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _xVelocity, jdouble _yVelocity, jdouble _zVelocity)
|
|
||||||
{
|
|
||||||
FAudioGMS_SetListenerVelocity(_xVelocity, _yVelocity, _zVelocity);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1SetListenerOrientation
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis, jdouble _xFront, jdouble _yFront, jdouble _zFront, jdouble _xTop, jdouble _yTop, jdouble _zTop)
|
|
||||||
{
|
|
||||||
FAudioGMS_SetListenerOrientation(_xFront, _yFront, _zFront, _xTop, _yTop, _zTop);
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1PauseAll
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis)
|
|
||||||
{
|
|
||||||
FAudioGMS_PauseAll();
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1ResumeAll
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis)
|
|
||||||
{
|
|
||||||
FAudioGMS_ResumeAll();
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1StopAll
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis)
|
|
||||||
{
|
|
||||||
FAudioGMS_StopAll();
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1Update
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis)
|
|
||||||
{
|
|
||||||
FAudioGMS_Update();
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
|
||||||
Java_org_screwyoyo_faudiogms_FAudioGMSNative_FAudioGMS_1Destroy
|
|
||||||
(JNIEnv* jniEnv, jclass jniThis)
|
|
||||||
{
|
|
||||||
FAudioGMS_Destroy();
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#endif /* __ANDROID__ */
|
|
||||||
|
|
||||||
/* Do nothing for other platforms, because they, thankly, do not require JNI bindings... */
|
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
cd /d %~dp0
|
|
||||||
mkdir buildandroid
|
|
||||||
|
|
||||||
call ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=Android.mk APP_ABI="armeabi-v7a arm64-v8a x86 x86_64" APP_PLATFORM=android-16 APP_MODULES="SDL2 FAudio_static FAudioGMS" NDK_OUT=buildandroid\obj NDK_LIBS_OUT=buildandroid\lib
|
|
||||||
|
|
||||||
xcopy /e /r /y buildandroid\lib ..\gamemaker\extensions\FAudioGMS\AndroidSource\libs
|
|
||||||
rd /s /q buildandroid
|
|
|
@ -1,24 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cd `dirname $0`
|
|
||||||
# rm -rf buildandroid
|
|
||||||
mkdir -p buildandroid
|
|
||||||
|
|
||||||
# Make sure you have ndk-build and Android Sdk stuff in your $PATH!
|
|
||||||
|
|
||||||
ndk-build \
|
|
||||||
NDK_PROJECT_PATH=null \
|
|
||||||
APP_BUILD_SCRIPT=Android.mk \
|
|
||||||
APP_ABI="armeabi-v7a arm64-v8a x86 x86_64" \
|
|
||||||
APP_PLATFORM=android-16 \
|
|
||||||
APP_MODULES="SDL2 FAudio_static FAudioGMS" \
|
|
||||||
NDK_OUT=buildandroid/obj \
|
|
||||||
NDK_LIBS_OUT=buildandroid/lib
|
|
||||||
|
|
||||||
|
|
||||||
# Update gamemaker project folder..
|
|
||||||
|
|
||||||
cp -rf buildandroid/lib/* ../gamemaker/extensions/FAudioGMS/AndroidSource/libs
|
|
||||||
rm -rf buildandroid
|
|
||||||
|
|
||||||
# we're done here.
|
|
|
@ -1,142 +0,0 @@
|
||||||
package ${YYAndroidPackageName}; /* this class will reside in Runner's package namespace */
|
|
||||||
|
|
||||||
import java.lang.String;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
|
|
||||||
import org.screwyoyo.faudiogms.FAudioGMSNative;
|
|
||||||
import org.libsdl.app.SDLActivity;
|
|
||||||
import org.libsdl.app.SDL;
|
|
||||||
import org.libsdl.app.SDLAudioManager;
|
|
||||||
import com.yoyogames.runner.RunnerJNILib;
|
|
||||||
|
|
||||||
import android.content.res.AssetManager;
|
|
||||||
|
|
||||||
public class FAudioGMSBridge extends FAudioGMSNative implements IExtensionBase
|
|
||||||
{
|
|
||||||
public SDLActivity sdl;
|
|
||||||
public boolean handlenativepause; /* automatically pause all sounds on onPause or not? */
|
|
||||||
public boolean paused; /* are we currently paused */
|
|
||||||
|
|
||||||
public FAudioGMSBridge()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
handlenativepause = true; /* set this to false if you wish to handle pauses manually */
|
|
||||||
paused = false; /* this one must be false at initialization */
|
|
||||||
SDL.setContext(RunnerJNILib.GetApplicationContext());
|
|
||||||
sdl = new SDLActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
SDL.setContext(RunnerJNILib.GetApplicationContext());
|
|
||||||
sdl.onCreate(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStart()
|
|
||||||
{
|
|
||||||
SDL.setContext(RunnerJNILib.GetApplicationContext());
|
|
||||||
sdl.onStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRestart()
|
|
||||||
{
|
|
||||||
onStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStop()
|
|
||||||
{
|
|
||||||
sdl.onStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDestroy()
|
|
||||||
{
|
|
||||||
sdl.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPause()
|
|
||||||
{
|
|
||||||
sdl.onPause();
|
|
||||||
if (handlenativepause && !paused)
|
|
||||||
{
|
|
||||||
paused = true;
|
|
||||||
FAudioGMS_PauseAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResume()
|
|
||||||
{
|
|
||||||
sdl.onResume();
|
|
||||||
if (handlenativepause && paused)
|
|
||||||
{
|
|
||||||
paused = false;
|
|
||||||
FAudioGMS_ResumeAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onWindowFocusChanged(boolean hasFocus)
|
|
||||||
{
|
|
||||||
sdl.onWindowFocusChanged(hasFocus);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onConfigurationChanged(Configuration newConfig)
|
|
||||||
{
|
|
||||||
sdl.onConfigurationChanged(newConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults)
|
|
||||||
{
|
|
||||||
sdl.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dialog onCreateDialog(int id)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onTouchEvent(final MotionEvent event)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onGenericMotionEvent(MotionEvent event)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean dispatchKeyEvent(KeyEvent event)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean performClick()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onNewIntent(android.content.Intent newIntent)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data){}
|
|
||||||
public boolean onKeyLongPress(int keyCode, KeyEvent event){return false;}
|
|
||||||
public boolean onCreateOptionsMenu( Menu menu ){return false;}
|
|
||||||
public boolean onOptionsItemSelected( MenuItem item ){return false;}
|
|
||||||
|
|
||||||
public boolean onKeyDown( int keyCode, KeyEvent event )
|
|
||||||
{ return false;}
|
|
||||||
public boolean onKeyUp( int keyCode, KeyEvent event ){return false;}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
plugins {
|
|
||||||
id 'com.android.library'
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 28
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compile 'com.getkeepsafe.relinker:relinker:1.4.4'
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="org.screwyoyo.faudiogms">
|
|
||||||
</manifest>
|
|
|
@ -1,22 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.hardware.usb.UsbDevice;
|
|
||||||
|
|
||||||
interface HIDDevice
|
|
||||||
{
|
|
||||||
public int getId();
|
|
||||||
public int getVendorId();
|
|
||||||
public int getProductId();
|
|
||||||
public String getSerialNumber();
|
|
||||||
public int getVersion();
|
|
||||||
public String getManufacturerName();
|
|
||||||
public String getProductName();
|
|
||||||
public UsbDevice getDevice();
|
|
||||||
public boolean open();
|
|
||||||
public int sendFeatureReport(byte[] report);
|
|
||||||
public int sendOutputReport(byte[] report);
|
|
||||||
public boolean getFeatureReport(byte[] report);
|
|
||||||
public void setFrozen(boolean frozen);
|
|
||||||
public void close();
|
|
||||||
public void shutdown();
|
|
||||||
}
|
|
|
@ -1,649 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
|
||||||
import android.bluetooth.BluetoothGatt;
|
|
||||||
import android.bluetooth.BluetoothGattCallback;
|
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
|
||||||
import android.bluetooth.BluetoothGattDescriptor;
|
|
||||||
import android.bluetooth.BluetoothManager;
|
|
||||||
import android.bluetooth.BluetoothProfile;
|
|
||||||
import android.bluetooth.BluetoothGattService;
|
|
||||||
import android.hardware.usb.UsbDevice;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.os.*;
|
|
||||||
|
|
||||||
//import com.android.internal.util.HexDump;
|
|
||||||
|
|
||||||
import java.lang.Runnable;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
|
|
||||||
|
|
||||||
private static final String TAG = "hidapi";
|
|
||||||
private HIDDeviceManager mManager;
|
|
||||||
private BluetoothDevice mDevice;
|
|
||||||
private int mDeviceId;
|
|
||||||
private BluetoothGatt mGatt;
|
|
||||||
private boolean mIsRegistered = false;
|
|
||||||
private boolean mIsConnected = false;
|
|
||||||
private boolean mIsChromebook = false;
|
|
||||||
private boolean mIsReconnecting = false;
|
|
||||||
private boolean mFrozen = false;
|
|
||||||
private LinkedList<GattOperation> mOperations;
|
|
||||||
GattOperation mCurrentOperation = null;
|
|
||||||
private Handler mHandler;
|
|
||||||
|
|
||||||
private static final int TRANSPORT_AUTO = 0;
|
|
||||||
private static final int TRANSPORT_BREDR = 1;
|
|
||||||
private static final int TRANSPORT_LE = 2;
|
|
||||||
|
|
||||||
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
|
|
||||||
|
|
||||||
static public final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
|
|
||||||
static public final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
|
|
||||||
static public final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
|
|
||||||
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
|
|
||||||
|
|
||||||
static class GattOperation {
|
|
||||||
private enum Operation {
|
|
||||||
CHR_READ,
|
|
||||||
CHR_WRITE,
|
|
||||||
ENABLE_NOTIFICATION
|
|
||||||
}
|
|
||||||
|
|
||||||
Operation mOp;
|
|
||||||
UUID mUuid;
|
|
||||||
byte[] mValue;
|
|
||||||
BluetoothGatt mGatt;
|
|
||||||
boolean mResult = true;
|
|
||||||
|
|
||||||
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
|
|
||||||
mGatt = gatt;
|
|
||||||
mOp = operation;
|
|
||||||
mUuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
|
|
||||||
mGatt = gatt;
|
|
||||||
mOp = operation;
|
|
||||||
mUuid = uuid;
|
|
||||||
mValue = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
// This is executed in main thread
|
|
||||||
BluetoothGattCharacteristic chr;
|
|
||||||
|
|
||||||
switch (mOp) {
|
|
||||||
case CHR_READ:
|
|
||||||
chr = getCharacteristic(mUuid);
|
|
||||||
//Log.v(TAG, "Reading characteristic " + chr.getUuid());
|
|
||||||
if (!mGatt.readCharacteristic(chr)) {
|
|
||||||
Log.e(TAG, "Unable to read characteristic " + mUuid.toString());
|
|
||||||
mResult = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mResult = true;
|
|
||||||
break;
|
|
||||||
case CHR_WRITE:
|
|
||||||
chr = getCharacteristic(mUuid);
|
|
||||||
//Log.v(TAG, "Writing characteristic " + chr.getUuid() + " value=" + HexDump.toHexString(value));
|
|
||||||
chr.setValue(mValue);
|
|
||||||
if (!mGatt.writeCharacteristic(chr)) {
|
|
||||||
Log.e(TAG, "Unable to write characteristic " + mUuid.toString());
|
|
||||||
mResult = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mResult = true;
|
|
||||||
break;
|
|
||||||
case ENABLE_NOTIFICATION:
|
|
||||||
chr = getCharacteristic(mUuid);
|
|
||||||
//Log.v(TAG, "Writing descriptor of " + chr.getUuid());
|
|
||||||
if (chr != null) {
|
|
||||||
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
|
|
||||||
if (cccd != null) {
|
|
||||||
int properties = chr.getProperties();
|
|
||||||
byte[] value;
|
|
||||||
if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == BluetoothGattCharacteristic.PROPERTY_NOTIFY) {
|
|
||||||
value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
|
|
||||||
} else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) == BluetoothGattCharacteristic.PROPERTY_INDICATE) {
|
|
||||||
value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Unable to start notifications on input characteristic");
|
|
||||||
mResult = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGatt.setCharacteristicNotification(chr, true);
|
|
||||||
cccd.setValue(value);
|
|
||||||
if (!mGatt.writeDescriptor(cccd)) {
|
|
||||||
Log.e(TAG, "Unable to write descriptor " + mUuid.toString());
|
|
||||||
mResult = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mResult = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean finish() {
|
|
||||||
return mResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
|
|
||||||
BluetoothGattService valveService = mGatt.getService(steamControllerService);
|
|
||||||
if (valveService == null)
|
|
||||||
return null;
|
|
||||||
return valveService.getCharacteristic(uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public GattOperation readCharacteristic(BluetoothGatt gatt, UUID uuid) {
|
|
||||||
return new GattOperation(gatt, Operation.CHR_READ, uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public GattOperation writeCharacteristic(BluetoothGatt gatt, UUID uuid, byte[] value) {
|
|
||||||
return new GattOperation(gatt, Operation.CHR_WRITE, uuid, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
|
|
||||||
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
|
|
||||||
mManager = manager;
|
|
||||||
mDevice = device;
|
|
||||||
mDeviceId = mManager.getDeviceIDForIdentifier(getIdentifier());
|
|
||||||
mIsRegistered = false;
|
|
||||||
mIsChromebook = mManager.getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management");
|
|
||||||
mOperations = new LinkedList<GattOperation>();
|
|
||||||
mHandler = new Handler(Looper.getMainLooper());
|
|
||||||
|
|
||||||
mGatt = connectGatt();
|
|
||||||
// final HIDDeviceBLESteamController finalThis = this;
|
|
||||||
// mHandler.postDelayed(new Runnable() {
|
|
||||||
// @Override
|
|
||||||
// public void run() {
|
|
||||||
// finalThis.checkConnectionForChromebookIssue();
|
|
||||||
// }
|
|
||||||
// }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIdentifier() {
|
|
||||||
return String.format("SteamController.%s", mDevice.getAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
public BluetoothGatt getGatt() {
|
|
||||||
return mGatt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Because on Chromebooks we show up as a dual-mode device, it will attempt to connect TRANSPORT_AUTO, which will use TRANSPORT_BREDR instead
|
|
||||||
// of TRANSPORT_LE. Let's force ourselves to connect low energy.
|
|
||||||
private BluetoothGatt connectGatt(boolean managed) {
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
try {
|
|
||||||
return mDevice.connectGatt(mManager.getContext(), managed, this, TRANSPORT_LE);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return mDevice.connectGatt(mManager.getContext(), managed, this);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return mDevice.connectGatt(mManager.getContext(), managed, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private BluetoothGatt connectGatt() {
|
|
||||||
return connectGatt(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getConnectionState() {
|
|
||||||
|
|
||||||
Context context = mManager.getContext();
|
|
||||||
if (context == null) {
|
|
||||||
// We are lacking any context to get our Bluetooth information. We'll just assume disconnected.
|
|
||||||
return BluetoothProfile.STATE_DISCONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
BluetoothManager btManager = (BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE);
|
|
||||||
if (btManager == null) {
|
|
||||||
// This device doesn't support Bluetooth. We should never be here, because how did
|
|
||||||
// we instantiate a device to start with?
|
|
||||||
return BluetoothProfile.STATE_DISCONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return btManager.getConnectionState(mDevice, BluetoothProfile.GATT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reconnect() {
|
|
||||||
|
|
||||||
if (getConnectionState() != BluetoothProfile.STATE_CONNECTED) {
|
|
||||||
mGatt.disconnect();
|
|
||||||
mGatt = connectGatt();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void checkConnectionForChromebookIssue() {
|
|
||||||
if (!mIsChromebook) {
|
|
||||||
// We only do this on Chromebooks, because otherwise it's really annoying to just attempt
|
|
||||||
// over and over.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int connectionState = getConnectionState();
|
|
||||||
|
|
||||||
switch (connectionState) {
|
|
||||||
case BluetoothProfile.STATE_CONNECTED:
|
|
||||||
if (!mIsConnected) {
|
|
||||||
// We are in the Bad Chromebook Place. We can force a disconnect
|
|
||||||
// to try to recover.
|
|
||||||
Log.v(TAG, "Chromebook: We are in a very bad state; the controller shows as connected in the underlying Bluetooth layer, but we never received a callback. Forcing a reconnect.");
|
|
||||||
mIsReconnecting = true;
|
|
||||||
mGatt.disconnect();
|
|
||||||
mGatt = connectGatt(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (!isRegistered()) {
|
|
||||||
if (mGatt.getServices().size() > 0) {
|
|
||||||
Log.v(TAG, "Chromebook: We are connected to a controller, but never got our registration. Trying to recover.");
|
|
||||||
probeService(this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log.v(TAG, "Chromebook: We are connected to a controller, but never discovered services. Trying to recover.");
|
|
||||||
mIsReconnecting = true;
|
|
||||||
mGatt.disconnect();
|
|
||||||
mGatt = connectGatt(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log.v(TAG, "Chromebook: We are connected, and registered. Everything's good!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.STATE_DISCONNECTED:
|
|
||||||
Log.v(TAG, "Chromebook: We have either been disconnected, or the Chromebook BtGatt.ContextMap bug has bitten us. Attempting a disconnect/reconnect, but we may not be able to recover.");
|
|
||||||
|
|
||||||
mIsReconnecting = true;
|
|
||||||
mGatt.disconnect();
|
|
||||||
mGatt = connectGatt(false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BluetoothProfile.STATE_CONNECTING:
|
|
||||||
Log.v(TAG, "Chromebook: We're still trying to connect. Waiting a bit longer.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
final HIDDeviceBLESteamController finalThis = this;
|
|
||||||
mHandler.postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
finalThis.checkConnectionForChromebookIssue();
|
|
||||||
}
|
|
||||||
}, CHROMEBOOK_CONNECTION_CHECK_INTERVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isRegistered() {
|
|
||||||
return mIsRegistered;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setRegistered() {
|
|
||||||
mIsRegistered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean probeService(HIDDeviceBLESteamController controller) {
|
|
||||||
|
|
||||||
if (isRegistered()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mIsConnected) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.v(TAG, "probeService controller=" + controller);
|
|
||||||
|
|
||||||
for (BluetoothGattService service : mGatt.getServices()) {
|
|
||||||
if (service.getUuid().equals(steamControllerService)) {
|
|
||||||
Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
|
|
||||||
|
|
||||||
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
|
|
||||||
if (chr.getUuid().equals(inputCharacteristic)) {
|
|
||||||
Log.v(TAG, "Found input characteristic");
|
|
||||||
// Start notifications
|
|
||||||
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
|
|
||||||
if (cccd != null) {
|
|
||||||
enableNotification(chr.getUuid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mGatt.getServices().size() == 0) && mIsChromebook && !mIsReconnecting) {
|
|
||||||
Log.e(TAG, "Chromebook: Discovered services were empty; this almost certainly means the BtGatt.ContextMap bug has bitten us.");
|
|
||||||
mIsConnected = false;
|
|
||||||
mIsReconnecting = true;
|
|
||||||
mGatt.disconnect();
|
|
||||||
mGatt = connectGatt(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void finishCurrentGattOperation() {
|
|
||||||
GattOperation op = null;
|
|
||||||
synchronized (mOperations) {
|
|
||||||
if (mCurrentOperation != null) {
|
|
||||||
op = mCurrentOperation;
|
|
||||||
mCurrentOperation = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (op != null) {
|
|
||||||
boolean result = op.finish(); // TODO: Maybe in main thread as well?
|
|
||||||
|
|
||||||
// Our operation failed, let's add it back to the beginning of our queue.
|
|
||||||
if (!result) {
|
|
||||||
mOperations.addFirst(op);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
executeNextGattOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executeNextGattOperation() {
|
|
||||||
synchronized (mOperations) {
|
|
||||||
if (mCurrentOperation != null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mOperations.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
mCurrentOperation = mOperations.removeFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run in main thread
|
|
||||||
mHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (mOperations) {
|
|
||||||
if (mCurrentOperation == null) {
|
|
||||||
Log.e(TAG, "Current operation null in executor?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurrentOperation.run();
|
|
||||||
// now wait for the GATT callback and when it comes, finish this operation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void queueGattOperation(GattOperation op) {
|
|
||||||
synchronized (mOperations) {
|
|
||||||
mOperations.add(op);
|
|
||||||
}
|
|
||||||
executeNextGattOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableNotification(UUID chrUuid) {
|
|
||||||
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);
|
|
||||||
queueGattOperation(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeCharacteristic(UUID uuid, byte[] value) {
|
|
||||||
GattOperation op = HIDDeviceBLESteamController.GattOperation.writeCharacteristic(mGatt, uuid, value);
|
|
||||||
queueGattOperation(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void readCharacteristic(UUID uuid) {
|
|
||||||
GattOperation op = HIDDeviceBLESteamController.GattOperation.readCharacteristic(mGatt, uuid);
|
|
||||||
queueGattOperation(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
////////////// BluetoothGattCallback overridden methods
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void onConnectionStateChange(BluetoothGatt g, int status, int newState) {
|
|
||||||
//Log.v(TAG, "onConnectionStateChange status=" + status + " newState=" + newState);
|
|
||||||
mIsReconnecting = false;
|
|
||||||
if (newState == 2) {
|
|
||||||
mIsConnected = true;
|
|
||||||
// Run directly, without GattOperation
|
|
||||||
if (!isRegistered()) {
|
|
||||||
mHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mGatt.discoverServices();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (newState == 0) {
|
|
||||||
mIsConnected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disconnection is handled in SteamLink using the ACTION_ACL_DISCONNECTED Intent.
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
|
||||||
//Log.v(TAG, "onServicesDiscovered status=" + status);
|
|
||||||
if (status == 0) {
|
|
||||||
if (gatt.getServices().size() == 0) {
|
|
||||||
Log.v(TAG, "onServicesDiscovered returned zero services; something has gone horribly wrong down in Android's Bluetooth stack.");
|
|
||||||
mIsReconnecting = true;
|
|
||||||
mIsConnected = false;
|
|
||||||
gatt.disconnect();
|
|
||||||
mGatt = connectGatt(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
probeService(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
|
||||||
//Log.v(TAG, "onCharacteristicRead status=" + status + " uuid=" + characteristic.getUuid());
|
|
||||||
|
|
||||||
if (characteristic.getUuid().equals(reportCharacteristic) && !mFrozen) {
|
|
||||||
mManager.HIDDeviceFeatureReport(getId(), characteristic.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
finishCurrentGattOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
|
||||||
//Log.v(TAG, "onCharacteristicWrite status=" + status + " uuid=" + characteristic.getUuid());
|
|
||||||
|
|
||||||
if (characteristic.getUuid().equals(reportCharacteristic)) {
|
|
||||||
// Only register controller with the native side once it has been fully configured
|
|
||||||
if (!isRegistered()) {
|
|
||||||
Log.v(TAG, "Registering Steam Controller with ID: " + getId());
|
|
||||||
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0);
|
|
||||||
setRegistered();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finishCurrentGattOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
|
|
||||||
// Enable this for verbose logging of controller input reports
|
|
||||||
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
|
|
||||||
|
|
||||||
if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {
|
|
||||||
mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
|
||||||
//Log.v(TAG, "onDescriptorRead status=" + status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
|
||||||
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
|
|
||||||
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
|
|
||||||
|
|
||||||
if (chr.getUuid().equals(inputCharacteristic)) {
|
|
||||||
boolean hasWrittenInputDescriptor = true;
|
|
||||||
BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);
|
|
||||||
if (reportChr != null) {
|
|
||||||
Log.v(TAG, "Writing report characteristic to enter valve mode");
|
|
||||||
reportChr.setValue(enterValveMode);
|
|
||||||
gatt.writeCharacteristic(reportChr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finishCurrentGattOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
|
|
||||||
//Log.v(TAG, "onReliableWriteCompleted status=" + status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
|
|
||||||
//Log.v(TAG, "onReadRemoteRssi status=" + status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
|
|
||||||
//Log.v(TAG, "onMtuChanged status=" + status);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////// Public API
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return mDeviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVendorId() {
|
|
||||||
// Valve Corporation
|
|
||||||
final int VALVE_USB_VID = 0x28DE;
|
|
||||||
return VALVE_USB_VID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getProductId() {
|
|
||||||
// We don't have an easy way to query from the Bluetooth device, but we know what it is
|
|
||||||
final int D0G_BLE2_PID = 0x1106;
|
|
||||||
return D0G_BLE2_PID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSerialNumber() {
|
|
||||||
// This will be read later via feature report by Steam
|
|
||||||
return "12345";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVersion() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getManufacturerName() {
|
|
||||||
return "Valve Corporation";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProductName() {
|
|
||||||
return "Steam Controller";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UsbDevice getDevice() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean open() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int sendFeatureReport(byte[] report) {
|
|
||||||
if (!isRegistered()) {
|
|
||||||
Log.e(TAG, "Attempted sendFeatureReport before Steam Controller is registered!");
|
|
||||||
if (mIsConnected) {
|
|
||||||
probeService(this);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to skip the first byte, as that doesn't go over the air
|
|
||||||
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
|
|
||||||
//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(actual_report));
|
|
||||||
writeCharacteristic(reportCharacteristic, actual_report);
|
|
||||||
return report.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int sendOutputReport(byte[] report) {
|
|
||||||
if (!isRegistered()) {
|
|
||||||
Log.e(TAG, "Attempted sendOutputReport before Steam Controller is registered!");
|
|
||||||
if (mIsConnected) {
|
|
||||||
probeService(this);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(report));
|
|
||||||
writeCharacteristic(reportCharacteristic, report);
|
|
||||||
return report.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getFeatureReport(byte[] report) {
|
|
||||||
if (!isRegistered()) {
|
|
||||||
Log.e(TAG, "Attempted getFeatureReport before Steam Controller is registered!");
|
|
||||||
if (mIsConnected) {
|
|
||||||
probeService(this);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Log.v(TAG, "getFeatureReport");
|
|
||||||
readCharacteristic(reportCharacteristic);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFrozen(boolean frozen) {
|
|
||||||
mFrozen = frozen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdown() {
|
|
||||||
close();
|
|
||||||
|
|
||||||
BluetoothGatt g = mGatt;
|
|
||||||
if (g != null) {
|
|
||||||
g.disconnect();
|
|
||||||
g.close();
|
|
||||||
mGatt = null;
|
|
||||||
}
|
|
||||||
mManager = null;
|
|
||||||
mIsRegistered = false;
|
|
||||||
mIsConnected = false;
|
|
||||||
mOperations.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,685 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
|
||||||
import android.bluetooth.BluetoothManager;
|
|
||||||
import android.bluetooth.BluetoothProfile;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.hardware.usb.*;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class HIDDeviceManager {
|
|
||||||
private static final String TAG = "hidapi";
|
|
||||||
private static final String ACTION_USB_PERMISSION = "org.libsdl.app.USB_PERMISSION";
|
|
||||||
|
|
||||||
private static HIDDeviceManager sManager;
|
|
||||||
private static int sManagerRefCount = 0;
|
|
||||||
|
|
||||||
public static HIDDeviceManager acquire(Context context) {
|
|
||||||
if (sManagerRefCount == 0) {
|
|
||||||
sManager = new HIDDeviceManager(context);
|
|
||||||
}
|
|
||||||
++sManagerRefCount;
|
|
||||||
return sManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void release(HIDDeviceManager manager) {
|
|
||||||
if (manager == sManager) {
|
|
||||||
--sManagerRefCount;
|
|
||||||
if (sManagerRefCount == 0) {
|
|
||||||
sManager.close();
|
|
||||||
sManager = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context mContext;
|
|
||||||
private HashMap<Integer, HIDDevice> mDevicesById = new HashMap<Integer, HIDDevice>();
|
|
||||||
private HashMap<BluetoothDevice, HIDDeviceBLESteamController> mBluetoothDevices = new HashMap<BluetoothDevice, HIDDeviceBLESteamController>();
|
|
||||||
private int mNextDeviceId = 0;
|
|
||||||
private SharedPreferences mSharedPreferences = null;
|
|
||||||
private boolean mIsChromebook = false;
|
|
||||||
private UsbManager mUsbManager;
|
|
||||||
private Handler mHandler;
|
|
||||||
private BluetoothManager mBluetoothManager;
|
|
||||||
private List<BluetoothDevice> mLastBluetoothDevices;
|
|
||||||
|
|
||||||
private final BroadcastReceiver mUsbBroadcast = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
String action = intent.getAction();
|
|
||||||
if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
|
|
||||||
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
|
||||||
handleUsbDeviceAttached(usbDevice);
|
|
||||||
} else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
|
|
||||||
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
|
||||||
handleUsbDeviceDetached(usbDevice);
|
|
||||||
} else if (action.equals(HIDDeviceManager.ACTION_USB_PERMISSION)) {
|
|
||||||
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
|
||||||
handleUsbDevicePermission(usbDevice, intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final BroadcastReceiver mBluetoothBroadcast = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
String action = intent.getAction();
|
|
||||||
// Bluetooth device was connected. If it was a Steam Controller, handle it
|
|
||||||
if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
|
|
||||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
|
||||||
Log.d(TAG, "Bluetooth device connected: " + device);
|
|
||||||
|
|
||||||
if (isSteamController(device)) {
|
|
||||||
connectBluetoothDevice(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bluetooth device was disconnected, remove from controller manager (if any)
|
|
||||||
if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
|
|
||||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
|
||||||
Log.d(TAG, "Bluetooth device disconnected: " + device);
|
|
||||||
|
|
||||||
disconnectBluetoothDevice(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private HIDDeviceManager(final Context context) {
|
|
||||||
mContext = context;
|
|
||||||
|
|
||||||
// Make sure we have the HIDAPI library loaded with the native functions
|
|
||||||
try {
|
|
||||||
SDL.loadLibrary("hidapi");
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Log.w(TAG, "Couldn't load hidapi: " + e.toString());
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
||||||
builder.setCancelable(false);
|
|
||||||
builder.setTitle("SDL HIDAPI Error");
|
|
||||||
builder.setMessage("Please report the following error to the SDL maintainers: " + e.getMessage());
|
|
||||||
builder.setNegativeButton("Quit", new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
try {
|
|
||||||
// If our context is an activity, exit rather than crashing when we can't
|
|
||||||
// call our native functions.
|
|
||||||
Activity activity = (Activity)context;
|
|
||||||
|
|
||||||
activity.finish();
|
|
||||||
}
|
|
||||||
catch (ClassCastException cce) {
|
|
||||||
// Context wasn't an activity, there's nothing we can do. Give up and return.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.show();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDDeviceRegisterCallback();
|
|
||||||
|
|
||||||
mSharedPreferences = mContext.getSharedPreferences("hidapi", Context.MODE_PRIVATE);
|
|
||||||
mIsChromebook = mContext.getPackageManager().hasSystemFeature("org.chromium.arc.device_management");
|
|
||||||
|
|
||||||
// if (shouldClear) {
|
|
||||||
// SharedPreferences.Editor spedit = mSharedPreferences.edit();
|
|
||||||
// spedit.clear();
|
|
||||||
// spedit.commit();
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
{
|
|
||||||
mNextDeviceId = mSharedPreferences.getInt("next_device_id", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
initializeUSB();
|
|
||||||
initializeBluetooth();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context getContext() {
|
|
||||||
return mContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDeviceIDForIdentifier(String identifier) {
|
|
||||||
SharedPreferences.Editor spedit = mSharedPreferences.edit();
|
|
||||||
|
|
||||||
int result = mSharedPreferences.getInt(identifier, 0);
|
|
||||||
if (result == 0) {
|
|
||||||
result = mNextDeviceId++;
|
|
||||||
spedit.putInt("next_device_id", mNextDeviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
spedit.putInt(identifier, result);
|
|
||||||
spedit.commit();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeUSB() {
|
|
||||||
mUsbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Logging
|
|
||||||
for (UsbDevice device : mUsbManager.getDeviceList().values()) {
|
|
||||||
Log.i(TAG,"Path: " + device.getDeviceName());
|
|
||||||
Log.i(TAG,"Manufacturer: " + device.getManufacturerName());
|
|
||||||
Log.i(TAG,"Product: " + device.getProductName());
|
|
||||||
Log.i(TAG,"ID: " + device.getDeviceId());
|
|
||||||
Log.i(TAG,"Class: " + device.getDeviceClass());
|
|
||||||
Log.i(TAG,"Protocol: " + device.getDeviceProtocol());
|
|
||||||
Log.i(TAG,"Vendor ID " + device.getVendorId());
|
|
||||||
Log.i(TAG,"Product ID: " + device.getProductId());
|
|
||||||
Log.i(TAG,"Interface count: " + device.getInterfaceCount());
|
|
||||||
Log.i(TAG,"---------------------------------------");
|
|
||||||
|
|
||||||
// Get interface details
|
|
||||||
for (int index = 0; index < device.getInterfaceCount(); index++) {
|
|
||||||
UsbInterface mUsbInterface = device.getInterface(index);
|
|
||||||
Log.i(TAG," ***** *****");
|
|
||||||
Log.i(TAG," Interface index: " + index);
|
|
||||||
Log.i(TAG," Interface ID: " + mUsbInterface.getId());
|
|
||||||
Log.i(TAG," Interface class: " + mUsbInterface.getInterfaceClass());
|
|
||||||
Log.i(TAG," Interface subclass: " + mUsbInterface.getInterfaceSubclass());
|
|
||||||
Log.i(TAG," Interface protocol: " + mUsbInterface.getInterfaceProtocol());
|
|
||||||
Log.i(TAG," Endpoint count: " + mUsbInterface.getEndpointCount());
|
|
||||||
|
|
||||||
// Get endpoint details
|
|
||||||
for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++)
|
|
||||||
{
|
|
||||||
UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);
|
|
||||||
Log.i(TAG," ++++ ++++ ++++");
|
|
||||||
Log.i(TAG," Endpoint index: " + epi);
|
|
||||||
Log.i(TAG," Attributes: " + mEndpoint.getAttributes());
|
|
||||||
Log.i(TAG," Direction: " + mEndpoint.getDirection());
|
|
||||||
Log.i(TAG," Number: " + mEndpoint.getEndpointNumber());
|
|
||||||
Log.i(TAG," Interval: " + mEndpoint.getInterval());
|
|
||||||
Log.i(TAG," Packet size: " + mEndpoint.getMaxPacketSize());
|
|
||||||
Log.i(TAG," Type: " + mEndpoint.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.i(TAG," No more devices connected.");
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Register for USB broadcasts and permission completions
|
|
||||||
IntentFilter filter = new IntentFilter();
|
|
||||||
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
|
|
||||||
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
|
|
||||||
filter.addAction(HIDDeviceManager.ACTION_USB_PERMISSION);
|
|
||||||
mContext.registerReceiver(mUsbBroadcast, filter);
|
|
||||||
|
|
||||||
for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
|
|
||||||
handleUsbDeviceAttached(usbDevice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UsbManager getUSBManager() {
|
|
||||||
return mUsbManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void shutdownUSB() {
|
|
||||||
try {
|
|
||||||
mContext.unregisterReceiver(mUsbBroadcast);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// We may not have registered, that's okay
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isHIDDeviceInterface(UsbDevice usbDevice, UsbInterface usbInterface) {
|
|
||||||
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (isXbox360Controller(usbDevice, usbInterface) || isXboxOneController(usbDevice, usbInterface)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isXbox360Controller(UsbDevice usbDevice, UsbInterface usbInterface) {
|
|
||||||
final int XB360_IFACE_SUBCLASS = 93;
|
|
||||||
final int XB360_IFACE_PROTOCOL = 1; // Wired
|
|
||||||
final int XB360W_IFACE_PROTOCOL = 129; // Wireless
|
|
||||||
final int[] SUPPORTED_VENDORS = {
|
|
||||||
0x0079, // GPD Win 2
|
|
||||||
0x044f, // Thrustmaster
|
|
||||||
0x045e, // Microsoft
|
|
||||||
0x046d, // Logitech
|
|
||||||
0x056e, // Elecom
|
|
||||||
0x06a3, // Saitek
|
|
||||||
0x0738, // Mad Catz
|
|
||||||
0x07ff, // Mad Catz
|
|
||||||
0x0e6f, // PDP
|
|
||||||
0x0f0d, // Hori
|
|
||||||
0x1038, // SteelSeries
|
|
||||||
0x11c9, // Nacon
|
|
||||||
0x12ab, // Unknown
|
|
||||||
0x1430, // RedOctane
|
|
||||||
0x146b, // BigBen
|
|
||||||
0x1532, // Razer Sabertooth
|
|
||||||
0x15e4, // Numark
|
|
||||||
0x162e, // Joytech
|
|
||||||
0x1689, // Razer Onza
|
|
||||||
0x1949, // Lab126, Inc.
|
|
||||||
0x1bad, // Harmonix
|
|
||||||
0x24c6, // PowerA
|
|
||||||
};
|
|
||||||
|
|
||||||
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
|
|
||||||
usbInterface.getInterfaceSubclass() == XB360_IFACE_SUBCLASS &&
|
|
||||||
(usbInterface.getInterfaceProtocol() == XB360_IFACE_PROTOCOL ||
|
|
||||||
usbInterface.getInterfaceProtocol() == XB360W_IFACE_PROTOCOL)) {
|
|
||||||
int vendor_id = usbDevice.getVendorId();
|
|
||||||
for (int supportedVid : SUPPORTED_VENDORS) {
|
|
||||||
if (vendor_id == supportedVid) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterface) {
|
|
||||||
final int XB1_IFACE_SUBCLASS = 71;
|
|
||||||
final int XB1_IFACE_PROTOCOL = 208;
|
|
||||||
final int[] SUPPORTED_VENDORS = {
|
|
||||||
0x045e, // Microsoft
|
|
||||||
0x0738, // Mad Catz
|
|
||||||
0x0e6f, // PDP
|
|
||||||
0x0f0d, // Hori
|
|
||||||
0x1532, // Razer Wildcat
|
|
||||||
0x24c6, // PowerA
|
|
||||||
0x2e24, // Hyperkin
|
|
||||||
};
|
|
||||||
|
|
||||||
if (usbInterface.getId() == 0 &&
|
|
||||||
usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
|
|
||||||
usbInterface.getInterfaceSubclass() == XB1_IFACE_SUBCLASS &&
|
|
||||||
usbInterface.getInterfaceProtocol() == XB1_IFACE_PROTOCOL) {
|
|
||||||
int vendor_id = usbDevice.getVendorId();
|
|
||||||
for (int supportedVid : SUPPORTED_VENDORS) {
|
|
||||||
if (vendor_id == supportedVid) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUsbDeviceAttached(UsbDevice usbDevice) {
|
|
||||||
connectHIDDeviceUSB(usbDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUsbDeviceDetached(UsbDevice usbDevice) {
|
|
||||||
List<Integer> devices = new ArrayList<Integer>();
|
|
||||||
for (HIDDevice device : mDevicesById.values()) {
|
|
||||||
if (usbDevice.equals(device.getDevice())) {
|
|
||||||
devices.add(device.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int id : devices) {
|
|
||||||
HIDDevice device = mDevicesById.get(id);
|
|
||||||
mDevicesById.remove(id);
|
|
||||||
device.shutdown();
|
|
||||||
HIDDeviceDisconnected(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUsbDevicePermission(UsbDevice usbDevice, boolean permission_granted) {
|
|
||||||
for (HIDDevice device : mDevicesById.values()) {
|
|
||||||
if (usbDevice.equals(device.getDevice())) {
|
|
||||||
boolean opened = false;
|
|
||||||
if (permission_granted) {
|
|
||||||
opened = device.open();
|
|
||||||
}
|
|
||||||
HIDDeviceOpenResult(device.getId(), opened);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void connectHIDDeviceUSB(UsbDevice usbDevice) {
|
|
||||||
synchronized (this) {
|
|
||||||
int interface_mask = 0;
|
|
||||||
for (int interface_index = 0; interface_index < usbDevice.getInterfaceCount(); interface_index++) {
|
|
||||||
UsbInterface usbInterface = usbDevice.getInterface(interface_index);
|
|
||||||
if (isHIDDeviceInterface(usbDevice, usbInterface)) {
|
|
||||||
// Check to see if we've already added this interface
|
|
||||||
// This happens with the Xbox Series X controller which has a duplicate interface 0, which is inactive
|
|
||||||
int interface_id = usbInterface.getId();
|
|
||||||
if ((interface_mask & (1 << interface_id)) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
interface_mask |= (1 << interface_id);
|
|
||||||
|
|
||||||
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
|
|
||||||
int id = device.getId();
|
|
||||||
mDevicesById.put(id, device);
|
|
||||||
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeBluetooth() {
|
|
||||||
Log.d(TAG, "Initializing Bluetooth");
|
|
||||||
|
|
||||||
if (mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18)) {
|
|
||||||
Log.d(TAG, "Couldn't initialize Bluetooth, this version of Android does not support Bluetooth LE");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find bonded bluetooth controllers and create SteamControllers for them
|
|
||||||
mBluetoothManager = (BluetoothManager)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
|
|
||||||
if (mBluetoothManager == null) {
|
|
||||||
// This device doesn't support Bluetooth.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BluetoothAdapter btAdapter = mBluetoothManager.getAdapter();
|
|
||||||
if (btAdapter == null) {
|
|
||||||
// This device has Bluetooth support in the codebase, but has no available adapters.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get our bonded devices.
|
|
||||||
for (BluetoothDevice device : btAdapter.getBondedDevices()) {
|
|
||||||
|
|
||||||
Log.d(TAG, "Bluetooth device available: " + device);
|
|
||||||
if (isSteamController(device)) {
|
|
||||||
connectBluetoothDevice(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: These don't work on Chromebooks, to my undying dismay.
|
|
||||||
IntentFilter filter = new IntentFilter();
|
|
||||||
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
|
|
||||||
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
|
|
||||||
mContext.registerReceiver(mBluetoothBroadcast, filter);
|
|
||||||
|
|
||||||
if (mIsChromebook) {
|
|
||||||
mHandler = new Handler(Looper.getMainLooper());
|
|
||||||
mLastBluetoothDevices = new ArrayList<BluetoothDevice>();
|
|
||||||
|
|
||||||
// final HIDDeviceManager finalThis = this;
|
|
||||||
// mHandler.postDelayed(new Runnable() {
|
|
||||||
// @Override
|
|
||||||
// public void run() {
|
|
||||||
// finalThis.chromebookConnectionHandler();
|
|
||||||
// }
|
|
||||||
// }, 5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void shutdownBluetooth() {
|
|
||||||
try {
|
|
||||||
mContext.unregisterReceiver(mBluetoothBroadcast);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// We may not have registered, that's okay
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chromebooks do not pass along ACTION_ACL_CONNECTED / ACTION_ACL_DISCONNECTED properly.
|
|
||||||
// This function provides a sort of dummy version of that, watching for changes in the
|
|
||||||
// connected devices and attempting to add controllers as things change.
|
|
||||||
public void chromebookConnectionHandler() {
|
|
||||||
if (!mIsChromebook) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<BluetoothDevice> disconnected = new ArrayList<BluetoothDevice>();
|
|
||||||
ArrayList<BluetoothDevice> connected = new ArrayList<BluetoothDevice>();
|
|
||||||
|
|
||||||
List<BluetoothDevice> currentConnected = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
|
|
||||||
|
|
||||||
for (BluetoothDevice bluetoothDevice : currentConnected) {
|
|
||||||
if (!mLastBluetoothDevices.contains(bluetoothDevice)) {
|
|
||||||
connected.add(bluetoothDevice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (BluetoothDevice bluetoothDevice : mLastBluetoothDevices) {
|
|
||||||
if (!currentConnected.contains(bluetoothDevice)) {
|
|
||||||
disconnected.add(bluetoothDevice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mLastBluetoothDevices = currentConnected;
|
|
||||||
|
|
||||||
for (BluetoothDevice bluetoothDevice : disconnected) {
|
|
||||||
disconnectBluetoothDevice(bluetoothDevice);
|
|
||||||
}
|
|
||||||
for (BluetoothDevice bluetoothDevice : connected) {
|
|
||||||
connectBluetoothDevice(bluetoothDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
final HIDDeviceManager finalThis = this;
|
|
||||||
mHandler.postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
finalThis.chromebookConnectionHandler();
|
|
||||||
}
|
|
||||||
}, 10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean connectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
|
||||||
Log.v(TAG, "connectBluetoothDevice device=" + bluetoothDevice);
|
|
||||||
synchronized (this) {
|
|
||||||
if (mBluetoothDevices.containsKey(bluetoothDevice)) {
|
|
||||||
Log.v(TAG, "Steam controller with address " + bluetoothDevice + " already exists, attempting reconnect");
|
|
||||||
|
|
||||||
HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);
|
|
||||||
device.reconnect();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
HIDDeviceBLESteamController device = new HIDDeviceBLESteamController(this, bluetoothDevice);
|
|
||||||
int id = device.getId();
|
|
||||||
mBluetoothDevices.put(bluetoothDevice, device);
|
|
||||||
mDevicesById.put(id, device);
|
|
||||||
|
|
||||||
// The Steam Controller will mark itself connected once initialization is complete
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
|
||||||
synchronized (this) {
|
|
||||||
HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);
|
|
||||||
if (device == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int id = device.getId();
|
|
||||||
mBluetoothDevices.remove(bluetoothDevice);
|
|
||||||
mDevicesById.remove(id);
|
|
||||||
device.shutdown();
|
|
||||||
HIDDeviceDisconnected(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSteamController(BluetoothDevice bluetoothDevice) {
|
|
||||||
// Sanity check. If you pass in a null device, by definition it is never a Steam Controller.
|
|
||||||
if (bluetoothDevice == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the device has no local name, we really don't want to try an equality check against it.
|
|
||||||
if (bluetoothDevice.getName() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void close() {
|
|
||||||
shutdownUSB();
|
|
||||||
shutdownBluetooth();
|
|
||||||
synchronized (this) {
|
|
||||||
for (HIDDevice device : mDevicesById.values()) {
|
|
||||||
device.shutdown();
|
|
||||||
}
|
|
||||||
mDevicesById.clear();
|
|
||||||
mBluetoothDevices.clear();
|
|
||||||
HIDDeviceReleaseCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFrozen(boolean frozen) {
|
|
||||||
synchronized (this) {
|
|
||||||
for (HIDDevice device : mDevicesById.values()) {
|
|
||||||
device.setFrozen(frozen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private HIDDevice getDevice(int id) {
|
|
||||||
synchronized (this) {
|
|
||||||
HIDDevice result = mDevicesById.get(id);
|
|
||||||
if (result == null) {
|
|
||||||
Log.v(TAG, "No device for id: " + id);
|
|
||||||
Log.v(TAG, "Available devices: " + mDevicesById.keySet());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
////////// JNI interface functions
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public boolean openDevice(int deviceID) {
|
|
||||||
Log.v(TAG, "openDevice deviceID=" + deviceID);
|
|
||||||
HIDDevice device = getDevice(deviceID);
|
|
||||||
if (device == null) {
|
|
||||||
HIDDeviceDisconnected(deviceID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look to see if this is a USB device and we have permission to access it
|
|
||||||
UsbDevice usbDevice = device.getDevice();
|
|
||||||
if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) {
|
|
||||||
HIDDeviceOpenPending(deviceID);
|
|
||||||
try {
|
|
||||||
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), 0));
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
|
|
||||||
HIDDeviceOpenResult(deviceID, false);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return device.open();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int sendOutputReport(int deviceID, byte[] report) {
|
|
||||||
try {
|
|
||||||
//Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length);
|
|
||||||
HIDDevice device;
|
|
||||||
device = getDevice(deviceID);
|
|
||||||
if (device == null) {
|
|
||||||
HIDDeviceDisconnected(deviceID);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return device.sendOutputReport(report);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int sendFeatureReport(int deviceID, byte[] report) {
|
|
||||||
try {
|
|
||||||
//Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length);
|
|
||||||
HIDDevice device;
|
|
||||||
device = getDevice(deviceID);
|
|
||||||
if (device == null) {
|
|
||||||
HIDDeviceDisconnected(deviceID);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return device.sendFeatureReport(report);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getFeatureReport(int deviceID, byte[] report) {
|
|
||||||
try {
|
|
||||||
//Log.v(TAG, "getFeatureReport deviceID=" + deviceID);
|
|
||||||
HIDDevice device;
|
|
||||||
device = getDevice(deviceID);
|
|
||||||
if (device == null) {
|
|
||||||
HIDDeviceDisconnected(deviceID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return device.getFeatureReport(report);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeDevice(int deviceID) {
|
|
||||||
try {
|
|
||||||
Log.v(TAG, "closeDevice deviceID=" + deviceID);
|
|
||||||
HIDDevice device;
|
|
||||||
device = getDevice(deviceID);
|
|
||||||
if (device == null) {
|
|
||||||
HIDDeviceDisconnected(deviceID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
device.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/////////////// Native methods
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private native void HIDDeviceRegisterCallback();
|
|
||||||
private native void HIDDeviceReleaseCallback();
|
|
||||||
|
|
||||||
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
|
|
||||||
native void HIDDeviceOpenPending(int deviceID);
|
|
||||||
native void HIDDeviceOpenResult(int deviceID, boolean opened);
|
|
||||||
native void HIDDeviceDisconnected(int deviceID);
|
|
||||||
|
|
||||||
native void HIDDeviceInputReport(int deviceID, byte[] report);
|
|
||||||
native void HIDDeviceFeatureReport(int deviceID, byte[] report);
|
|
||||||
}
|
|
|
@ -1,309 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.hardware.usb.*;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.Log;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
class HIDDeviceUSB implements HIDDevice {
|
|
||||||
|
|
||||||
private static final String TAG = "hidapi";
|
|
||||||
|
|
||||||
protected HIDDeviceManager mManager;
|
|
||||||
protected UsbDevice mDevice;
|
|
||||||
protected int mInterfaceIndex;
|
|
||||||
protected int mInterface;
|
|
||||||
protected int mDeviceId;
|
|
||||||
protected UsbDeviceConnection mConnection;
|
|
||||||
protected UsbEndpoint mInputEndpoint;
|
|
||||||
protected UsbEndpoint mOutputEndpoint;
|
|
||||||
protected InputThread mInputThread;
|
|
||||||
protected boolean mRunning;
|
|
||||||
protected boolean mFrozen;
|
|
||||||
|
|
||||||
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
|
|
||||||
mManager = manager;
|
|
||||||
mDevice = usbDevice;
|
|
||||||
mInterfaceIndex = interface_index;
|
|
||||||
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
|
|
||||||
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
|
|
||||||
mRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIdentifier() {
|
|
||||||
return String.format("%s/%x/%x/%d", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterfaceIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return mDeviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVendorId() {
|
|
||||||
return mDevice.getVendorId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getProductId() {
|
|
||||||
return mDevice.getProductId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSerialNumber() {
|
|
||||||
String result = null;
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
try {
|
|
||||||
result = mDevice.getSerialNumber();
|
|
||||||
}
|
|
||||||
catch (SecurityException exception) {
|
|
||||||
//Log.w(TAG, "App permissions mean we cannot get serial number for device " + getDeviceName() + " message: " + exception.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result == null) {
|
|
||||||
result = "";
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVersion() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getManufacturerName() {
|
|
||||||
String result = null;
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
result = mDevice.getManufacturerName();
|
|
||||||
}
|
|
||||||
if (result == null) {
|
|
||||||
result = String.format("%x", getVendorId());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProductName() {
|
|
||||||
String result = null;
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
result = mDevice.getProductName();
|
|
||||||
}
|
|
||||||
if (result == null) {
|
|
||||||
result = String.format("%x", getProductId());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UsbDevice getDevice() {
|
|
||||||
return mDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceName() {
|
|
||||||
return getManufacturerName() + " " + getProductName() + "(0x" + String.format("%x", getVendorId()) + "/0x" + String.format("%x", getProductId()) + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean open() {
|
|
||||||
mConnection = mManager.getUSBManager().openDevice(mDevice);
|
|
||||||
if (mConnection == null) {
|
|
||||||
Log.w(TAG, "Unable to open USB device " + getDeviceName());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force claim our interface
|
|
||||||
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
|
||||||
if (!mConnection.claimInterface(iface, true)) {
|
|
||||||
Log.w(TAG, "Failed to claim interfaces on USB device " + getDeviceName());
|
|
||||||
close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the endpoints
|
|
||||||
for (int j = 0; j < iface.getEndpointCount(); j++) {
|
|
||||||
UsbEndpoint endpt = iface.getEndpoint(j);
|
|
||||||
switch (endpt.getDirection()) {
|
|
||||||
case UsbConstants.USB_DIR_IN:
|
|
||||||
if (mInputEndpoint == null) {
|
|
||||||
mInputEndpoint = endpt;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UsbConstants.USB_DIR_OUT:
|
|
||||||
if (mOutputEndpoint == null) {
|
|
||||||
mOutputEndpoint = endpt;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the required endpoints were present
|
|
||||||
if (mInputEndpoint == null || mOutputEndpoint == null) {
|
|
||||||
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
|
|
||||||
close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start listening for input
|
|
||||||
mRunning = true;
|
|
||||||
mInputThread = new InputThread();
|
|
||||||
mInputThread.start();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int sendFeatureReport(byte[] report) {
|
|
||||||
int res = -1;
|
|
||||||
int offset = 0;
|
|
||||||
int length = report.length;
|
|
||||||
boolean skipped_report_id = false;
|
|
||||||
byte report_number = report[0];
|
|
||||||
|
|
||||||
if (report_number == 0x0) {
|
|
||||||
++offset;
|
|
||||||
--length;
|
|
||||||
skipped_report_id = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = mConnection.controlTransfer(
|
|
||||||
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT,
|
|
||||||
0x09/*HID set_report*/,
|
|
||||||
(3/*HID feature*/ << 8) | report_number,
|
|
||||||
mInterface,
|
|
||||||
report, offset, length,
|
|
||||||
1000/*timeout millis*/);
|
|
||||||
|
|
||||||
if (res < 0) {
|
|
||||||
Log.w(TAG, "sendFeatureReport() returned " + res + " on device " + getDeviceName());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skipped_report_id) {
|
|
||||||
++length;
|
|
||||||
}
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int sendOutputReport(byte[] report) {
|
|
||||||
int r = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
|
|
||||||
if (r != report.length) {
|
|
||||||
Log.w(TAG, "sendOutputReport() returned " + r + " on device " + getDeviceName());
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getFeatureReport(byte[] report) {
|
|
||||||
int res = -1;
|
|
||||||
int offset = 0;
|
|
||||||
int length = report.length;
|
|
||||||
boolean skipped_report_id = false;
|
|
||||||
byte report_number = report[0];
|
|
||||||
|
|
||||||
if (report_number == 0x0) {
|
|
||||||
/* Offset the return buffer by 1, so that the report ID
|
|
||||||
will remain in byte 0. */
|
|
||||||
++offset;
|
|
||||||
--length;
|
|
||||||
skipped_report_id = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = mConnection.controlTransfer(
|
|
||||||
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN,
|
|
||||||
0x01/*HID get_report*/,
|
|
||||||
(3/*HID feature*/ << 8) | report_number,
|
|
||||||
mInterface,
|
|
||||||
report, offset, length,
|
|
||||||
1000/*timeout millis*/);
|
|
||||||
|
|
||||||
if (res < 0) {
|
|
||||||
Log.w(TAG, "getFeatureReport() returned " + res + " on device " + getDeviceName());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skipped_report_id) {
|
|
||||||
++res;
|
|
||||||
++length;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] data;
|
|
||||||
if (res == length) {
|
|
||||||
data = report;
|
|
||||||
} else {
|
|
||||||
data = Arrays.copyOfRange(report, 0, res);
|
|
||||||
}
|
|
||||||
mManager.HIDDeviceFeatureReport(mDeviceId, data);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
mRunning = false;
|
|
||||||
if (mInputThread != null) {
|
|
||||||
while (mInputThread.isAlive()) {
|
|
||||||
mInputThread.interrupt();
|
|
||||||
try {
|
|
||||||
mInputThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// Keep trying until we're done
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mInputThread = null;
|
|
||||||
}
|
|
||||||
if (mConnection != null) {
|
|
||||||
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
|
||||||
mConnection.releaseInterface(iface);
|
|
||||||
mConnection.close();
|
|
||||||
mConnection = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdown() {
|
|
||||||
close();
|
|
||||||
mManager = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFrozen(boolean frozen) {
|
|
||||||
mFrozen = frozen;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected class InputThread extends Thread {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int packetSize = mInputEndpoint.getMaxPacketSize();
|
|
||||||
byte[] packet = new byte[packetSize];
|
|
||||||
while (mRunning) {
|
|
||||||
int r;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
r = mConnection.bulkTransfer(mInputEndpoint, packet, packetSize, 1000);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.v(TAG, "Exception in UsbDeviceConnection bulktransfer: " + e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (r < 0) {
|
|
||||||
// Could be a timeout or an I/O error
|
|
||||||
}
|
|
||||||
if (r > 0) {
|
|
||||||
byte[] data;
|
|
||||||
if (r == packetSize) {
|
|
||||||
data = packet;
|
|
||||||
} else {
|
|
||||||
data = Arrays.copyOfRange(packet, 0, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mFrozen) {
|
|
||||||
mManager.HIDDeviceInputReport(mDeviceId, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import java.lang.Class;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
SDL library initialization
|
|
||||||
*/
|
|
||||||
public class SDL {
|
|
||||||
|
|
||||||
// This function should be called first and sets up the native code
|
|
||||||
// so it can call into the Java classes
|
|
||||||
public static void setupJNI() {
|
|
||||||
SDLActivity.nativeSetupJNI();
|
|
||||||
SDLAudioManager.nativeSetupJNI();
|
|
||||||
SDLControllerManager.nativeSetupJNI();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function should be called each time the activity is started
|
|
||||||
public static void initialize() {
|
|
||||||
SDLActivity.initialize();
|
|
||||||
SDLAudioManager.initialize();
|
|
||||||
SDLControllerManager.initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function stores the current activity (SDL or not)
|
|
||||||
public static void setContext(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Context getContext() {
|
|
||||||
return mContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
|
||||||
|
|
||||||
if (libraryName == null) {
|
|
||||||
throw new NullPointerException("No library name provided.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Let's see if we have ReLinker available in the project. This is necessary for
|
|
||||||
// some projects that have huge numbers of local libraries bundled, and thus may
|
|
||||||
// trip a bug in Android's native library loader which ReLinker works around. (If
|
|
||||||
// loadLibrary works properly, ReLinker will simply use the normal Android method
|
|
||||||
// internally.)
|
|
||||||
//
|
|
||||||
// To use ReLinker, just add it as a dependency. For more information, see
|
|
||||||
// https://github.com/KeepSafe/ReLinker for ReLinker's repository.
|
|
||||||
//
|
|
||||||
Class<?> relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
|
|
||||||
Class<?> relinkListenerClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
|
|
||||||
Class<?> contextClass = mContext.getClassLoader().loadClass("android.content.Context");
|
|
||||||
Class<?> stringClass = mContext.getClassLoader().loadClass("java.lang.String");
|
|
||||||
|
|
||||||
// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
|
|
||||||
// they've changed during updates.
|
|
||||||
Method forceMethod = relinkClass.getDeclaredMethod("force");
|
|
||||||
Object relinkInstance = forceMethod.invoke(null);
|
|
||||||
Class<?> relinkInstanceClass = relinkInstance.getClass();
|
|
||||||
|
|
||||||
// Actually load the library!
|
|
||||||
Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass);
|
|
||||||
loadMethod.invoke(relinkInstance, mContext, libraryName, null, null);
|
|
||||||
}
|
|
||||||
catch (final Throwable e) {
|
|
||||||
// Fall back
|
|
||||||
try {
|
|
||||||
System.loadLibrary(libraryName);
|
|
||||||
}
|
|
||||||
catch (final UnsatisfiedLinkError ule) {
|
|
||||||
throw ule;
|
|
||||||
}
|
|
||||||
catch (final SecurityException se) {
|
|
||||||
throw se;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static Context mContext;
|
|
||||||
}
|
|
|
@ -1,616 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.app.UiModeManager;
|
|
||||||
import android.content.ClipboardManager;
|
|
||||||
import android.content.ClipData;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.hardware.Sensor;
|
|
||||||
import android.hardware.SensorEvent;
|
|
||||||
import android.hardware.SensorEventListener;
|
|
||||||
import android.hardware.SensorManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.text.InputType;
|
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.view.Display;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.InputDevice;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.PointerIcon;
|
|
||||||
import android.view.Surface;
|
|
||||||
import android.view.SurfaceHolder;
|
|
||||||
import android.view.SurfaceView;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.view.inputmethod.BaseInputConnection;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.view.inputmethod.InputConnection;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
SDL Activity
|
|
||||||
*/
|
|
||||||
public class SDLActivity {
|
|
||||||
private static final String TAG = "yoyo";
|
|
||||||
|
|
||||||
public static boolean mIsResumedCalled, mHasFocus;
|
|
||||||
|
|
||||||
public static Locale mCurrentLocale;
|
|
||||||
|
|
||||||
// Handle the state of the native layer
|
|
||||||
public enum NativeState {
|
|
||||||
INIT, RESUMED, PAUSED
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NativeState mNextNativeState;
|
|
||||||
public static NativeState mCurrentNativeState;
|
|
||||||
|
|
||||||
// Main components
|
|
||||||
public static SDLActivity mSingleton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL before loading the native shared libraries.
|
|
||||||
* It can be overridden to provide names of shared libraries to be loaded.
|
|
||||||
* The default implementation returns the defaults. It never returns null.
|
|
||||||
* An array returned by a new implementation must at least contain "SDL2".
|
|
||||||
* Also keep in mind that the order the libraries are loaded may matter.
|
|
||||||
* @return names of shared libraries to be loaded (e.g. "SDL2", "main").
|
|
||||||
*/
|
|
||||||
public String[] getLibraries() {
|
|
||||||
return new String[] {
|
|
||||||
"hidapi",
|
|
||||||
"SDL2",
|
|
||||||
"FAudioGMS"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the .so
|
|
||||||
public void loadLibraries() {
|
|
||||||
for (String lib : getLibraries()) {
|
|
||||||
SDL.loadLibrary(lib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initialize() {
|
|
||||||
// The static nature of the singleton and Android quirkyness force us to initialize everything here
|
|
||||||
// Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
|
|
||||||
mSingleton = null;
|
|
||||||
mIsResumedCalled = false;
|
|
||||||
mHasFocus = true;
|
|
||||||
mNextNativeState = NativeState.INIT;
|
|
||||||
mCurrentNativeState = NativeState.INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
Log.v(TAG, "Device: " + Build.DEVICE);
|
|
||||||
Log.v(TAG, "Model: " + Build.MODEL);
|
|
||||||
Log.v(TAG, "onCreate()");
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.currentThread().setName("SDLActivity");
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.v(TAG, "modify thread properties failed " + e.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load shared libraries
|
|
||||||
loadLibraries();
|
|
||||||
|
|
||||||
// Set up JNI
|
|
||||||
SDL.setupJNI();
|
|
||||||
|
|
||||||
// Initialize state
|
|
||||||
SDL.initialize();
|
|
||||||
|
|
||||||
// So we can call stuff from static callbacks
|
|
||||||
mSingleton = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pauseNativeThread() {
|
|
||||||
mNextNativeState = NativeState.PAUSED;
|
|
||||||
mIsResumedCalled = false;
|
|
||||||
|
|
||||||
SDLActivity.handleNativeState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resumeNativeThread() {
|
|
||||||
mNextNativeState = NativeState.RESUMED;
|
|
||||||
mIsResumedCalled = true;
|
|
||||||
|
|
||||||
SDLActivity.handleNativeState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Events
|
|
||||||
public void onPause() {
|
|
||||||
Log.v(TAG, "onPause()");
|
|
||||||
pauseNativeThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onResume() {
|
|
||||||
Log.v(TAG, "onResume()");
|
|
||||||
resumeNativeThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStop() {
|
|
||||||
Log.v(TAG, "onStop()");
|
|
||||||
pauseNativeThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onStart() {
|
|
||||||
Log.v(TAG, "onStart()");
|
|
||||||
resumeNativeThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onWindowFocusChanged(boolean hasFocus) {
|
|
||||||
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
|
|
||||||
|
|
||||||
mHasFocus = hasFocus;
|
|
||||||
if (hasFocus) {
|
|
||||||
mNextNativeState = NativeState.RESUMED;
|
|
||||||
SDLActivity.handleNativeState();
|
|
||||||
nativeFocusChanged(true);
|
|
||||||
} else {
|
|
||||||
nativeFocusChanged(false);
|
|
||||||
mNextNativeState = NativeState.PAUSED;
|
|
||||||
SDLActivity.handleNativeState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onLowMemory() {
|
|
||||||
Log.v(TAG, "onLowMemory()");
|
|
||||||
SDLActivity.nativeLowMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
|
||||||
Log.v(TAG, "onConfigurationChanged()");
|
|
||||||
|
|
||||||
if (mCurrentLocale == null || !mCurrentLocale.equals(newConfig.locale)) {
|
|
||||||
mCurrentLocale = newConfig.locale;
|
|
||||||
SDLActivity.onNativeLocaleChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDestroy() {
|
|
||||||
Log.v(TAG, "onDestroy()");
|
|
||||||
SDLActivity.nativeSendQuit();
|
|
||||||
SDLActivity.nativeQuit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by JNI from SDL.
|
|
||||||
public static void manualBackButton() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Transition to next state */
|
|
||||||
public static void handleNativeState() {
|
|
||||||
if (mNextNativeState == mCurrentNativeState) {
|
|
||||||
// Already in same state, discard.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try a transition to init state
|
|
||||||
if (mNextNativeState == NativeState.INIT) {
|
|
||||||
mCurrentNativeState = mNextNativeState;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try a transition to paused state
|
|
||||||
if (mNextNativeState == NativeState.PAUSED) {
|
|
||||||
nativePause();
|
|
||||||
mCurrentNativeState = mNextNativeState;
|
|
||||||
Log.i("yoyo", "SDL - PAUSE!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try a transition to resumed state
|
|
||||||
if (mNextNativeState == NativeState.RESUMED) {
|
|
||||||
nativeResume();
|
|
||||||
mCurrentNativeState = mNextNativeState;
|
|
||||||
Log.i("yoyo", "SDL - RESUME!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL if SDL did not handle a message itself.
|
|
||||||
* This happens if a received message contains an unsupported command.
|
|
||||||
* Method can be overwritten to handle Messages in a different class.
|
|
||||||
* @param command the command of the message.
|
|
||||||
* @param param the parameter of the message. May be null.
|
|
||||||
* @return if the message was handled in overridden method.
|
|
||||||
*/
|
|
||||||
public boolean onUnhandledMessage(int command, Object param) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Handler class for Messages from native SDL applications.
|
|
||||||
* It uses current Activities as target (e.g. for the title).
|
|
||||||
* static to prevent implicit references to enclosing object.
|
|
||||||
*/
|
|
||||||
public static class SDLCommandHandler extends Handler {
|
|
||||||
@Override
|
|
||||||
public void handleMessage(Message msg) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handler for the messages
|
|
||||||
Handler commandHandler = new SDLCommandHandler();
|
|
||||||
|
|
||||||
// Send a message from the SDLMain thread
|
|
||||||
boolean sendCommand(int command, Object data) {
|
|
||||||
Message msg = commandHandler.obtainMessage();
|
|
||||||
msg.arg1 = command;
|
|
||||||
msg.obj = data;
|
|
||||||
boolean result = commandHandler.sendMessage(msg);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// C functions we call
|
|
||||||
public static native int nativeSetupJNI();
|
|
||||||
public static native int nativeRunMain(String library, String function, Object arguments);
|
|
||||||
public static native void nativeLowMemory();
|
|
||||||
public static native void nativeSendQuit();
|
|
||||||
public static native void nativeQuit();
|
|
||||||
public static native void nativePause();
|
|
||||||
public static native void nativeResume();
|
|
||||||
public static native void nativeFocusChanged(boolean hasFocus);
|
|
||||||
public static native void onNativeDropFile(String filename);
|
|
||||||
public static native void nativeSetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float rate);
|
|
||||||
public static native void onNativeResize();
|
|
||||||
public static native void onNativeKeyDown(int keycode);
|
|
||||||
public static native void onNativeKeyUp(int keycode);
|
|
||||||
public static native boolean onNativeSoftReturnKey();
|
|
||||||
public static native void onNativeKeyboardFocusLost();
|
|
||||||
public static native void onNativeMouse(int button, int action, float x, float y, boolean relative);
|
|
||||||
public static native void onNativeTouch(int touchDevId, int pointerFingerId,
|
|
||||||
int action, float x,
|
|
||||||
float y, float p);
|
|
||||||
public static native void onNativeAccel(float x, float y, float z);
|
|
||||||
public static native void onNativeClipboardChanged();
|
|
||||||
public static native void onNativeSurfaceCreated();
|
|
||||||
public static native void onNativeSurfaceChanged();
|
|
||||||
public static native void onNativeSurfaceDestroyed();
|
|
||||||
public static native String nativeGetHint(String name);
|
|
||||||
public static native void nativeSetenv(String name, String value);
|
|
||||||
public static native void onNativeOrientationChanged(int orientation);
|
|
||||||
public static native void nativeAddTouch(int touchId, String name);
|
|
||||||
public static native void nativePermissionResult(int requestCode, boolean result);
|
|
||||||
public static native void onNativeLocaleChanged();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean setActivityTitle(String title) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void setWindowStyle(boolean fullscreen) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
* This is a static method for JNI convenience, it calls a non-static method
|
|
||||||
* so that is can be overridden
|
|
||||||
*/
|
|
||||||
public static void setOrientation(int w, int h, boolean resizable, String hint){
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This can be overridden
|
|
||||||
*/
|
|
||||||
public void setOrientationBis(int w, int h, boolean resizable, String hint){
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void minimizeWindow() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean shouldMinimizeOnFocusLoss() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean isScreenKeyboardShown(){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean supportsRelativeMouse(){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean setRelativeMouseEnabled(boolean enabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean sendMessage(int command, int param) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static Context getContext() {
|
|
||||||
return SDL.getContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean isAndroidTV() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double getDiagonal() {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean isTablet() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean isChromebook() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean isDeXMode() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static DisplayMetrics getDisplayDPI() {
|
|
||||||
return getContext().getResources().getDisplayMetrics();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean getManifestEnvironmentVariables() {
|
|
||||||
Log.i("yoyo", "sdl envvars req!");
|
|
||||||
nativeSetenv("SDL_ANDROID_BLOCK_ON_PAUSE", "1");
|
|
||||||
nativeSetenv("SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO", "1");
|
|
||||||
Log.i("yoyo", "sdl envvars ok!");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean showTextInput(int x, int y, int w, int h) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static Surface getNativeSurface() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void initTouch() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Messagebox
|
|
||||||
|
|
||||||
/** Result of current messagebox. Also used for blocking the calling thread. */
|
|
||||||
public final int[] messageboxSelection = new int[1];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
* Shows the messagebox from UI thread and block calling thread.
|
|
||||||
* buttonFlags, buttonIds and buttonTexts must have same length.
|
|
||||||
* @param buttonFlags array containing flags for every button.
|
|
||||||
* @param buttonIds array containing id for every button.
|
|
||||||
* @param buttonTexts array containing text for every button.
|
|
||||||
* @param colors null for default or array of length 5 containing colors.
|
|
||||||
* @return button id or -1.
|
|
||||||
*/
|
|
||||||
public int messageboxShowMessageBox(
|
|
||||||
final int flags,
|
|
||||||
final String title,
|
|
||||||
final String message,
|
|
||||||
final int[] buttonFlags,
|
|
||||||
final int[] buttonIds,
|
|
||||||
final String[] buttonTexts,
|
|
||||||
final int[] colors) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void messageboxCreateAndShow(Bundle args) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Runnable rehideSystemUi = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public void onSystemUiVisibilityChange(int visibility) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean clipboardHasText() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static String clipboardGetText() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void clipboardSetText(String string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static int createCustomCursor(int[] colors, int width, int height, int hotSpotX, int hotSpotY) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean setCustomCursor(int cursorID) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static boolean setSystemCursor(int cursorID) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void requestPermission(String permission, int requestCode) {
|
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
|
||||||
nativePermissionResult(requestCode, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Activity activity = (Activity)getContext();
|
|
||||||
if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
activity.requestPermissions(new String[]{permission}, requestCode);
|
|
||||||
} else {
|
|
||||||
nativePermissionResult(requestCode, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
||||||
boolean result = (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED);
|
|
||||||
nativePermissionResult(requestCode, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static int openURL(String url) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static int showToast(String message, int duration, int gravity, int xOffset, int yOffset) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Simple runnable to start the SDL application
|
|
||||||
*/
|
|
||||||
class SDLMain implements Runnable {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DISPLAY);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.v("SDL", "modify thread properties failed " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SDLInputConnection extends BaseInputConnection {
|
|
||||||
public SDLInputConnection(View targetView, boolean fullEditor) {
|
|
||||||
super(targetView, fullEditor);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean sendKeyEvent(KeyEvent event) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static native void nativeCommitText(String text, int newCursorPosition);
|
|
||||||
|
|
||||||
public native void nativeGenerateScancodeForUnichar(char c);
|
|
||||||
|
|
||||||
public native void nativeSetComposingText(String text, int newCursorPosition);
|
|
||||||
|
|
||||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,390 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.media.AudioFormat;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.media.AudioRecord;
|
|
||||||
import android.media.AudioTrack;
|
|
||||||
import android.media.MediaRecorder;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class SDLAudioManager
|
|
||||||
{
|
|
||||||
protected static final String TAG = "yoyo";
|
|
||||||
|
|
||||||
protected static AudioTrack mAudioTrack;
|
|
||||||
protected static AudioRecord mAudioRecord;
|
|
||||||
|
|
||||||
public static void initialize() {
|
|
||||||
mAudioTrack = null;
|
|
||||||
mAudioRecord = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio
|
|
||||||
|
|
||||||
protected static String getAudioFormatString(int audioFormat) {
|
|
||||||
switch (audioFormat) {
|
|
||||||
case AudioFormat.ENCODING_PCM_8BIT:
|
|
||||||
return "8-bit";
|
|
||||||
case AudioFormat.ENCODING_PCM_16BIT:
|
|
||||||
return "16-bit";
|
|
||||||
case AudioFormat.ENCODING_PCM_FLOAT:
|
|
||||||
return "float";
|
|
||||||
default:
|
|
||||||
return Integer.toString(audioFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
|
|
||||||
int channelConfig;
|
|
||||||
int sampleSize;
|
|
||||||
int frameSize;
|
|
||||||
|
|
||||||
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", requested " + desiredFrames + " frames of " + desiredChannels + " channel " + getAudioFormatString(audioFormat) + " audio at " + sampleRate + " Hz");
|
|
||||||
|
|
||||||
/* On older devices let's use known good settings */
|
|
||||||
if (Build.VERSION.SDK_INT < 21) {
|
|
||||||
if (desiredChannels > 2) {
|
|
||||||
desiredChannels = 2;
|
|
||||||
}
|
|
||||||
if (sampleRate < 8000) {
|
|
||||||
sampleRate = 8000;
|
|
||||||
} else if (sampleRate > 48000) {
|
|
||||||
sampleRate = 48000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
|
|
||||||
int minSDKVersion = (isCapture ? 23 : 21);
|
|
||||||
if (Build.VERSION.SDK_INT < minSDKVersion) {
|
|
||||||
audioFormat = AudioFormat.ENCODING_PCM_16BIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (audioFormat)
|
|
||||||
{
|
|
||||||
case AudioFormat.ENCODING_PCM_8BIT:
|
|
||||||
sampleSize = 1;
|
|
||||||
break;
|
|
||||||
case AudioFormat.ENCODING_PCM_16BIT:
|
|
||||||
sampleSize = 2;
|
|
||||||
break;
|
|
||||||
case AudioFormat.ENCODING_PCM_FLOAT:
|
|
||||||
sampleSize = 4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.v(TAG, "Requested format " + audioFormat + ", getting ENCODING_PCM_16BIT");
|
|
||||||
audioFormat = AudioFormat.ENCODING_PCM_16BIT;
|
|
||||||
sampleSize = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCapture) {
|
|
||||||
switch (desiredChannels) {
|
|
||||||
case 1:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_IN_MONO;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_IN_STEREO;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.v(TAG, "Requested " + desiredChannels + " channels, getting stereo");
|
|
||||||
desiredChannels = 2;
|
|
||||||
channelConfig = AudioFormat.CHANNEL_IN_STEREO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (desiredChannels) {
|
|
||||||
case 1:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_MONO;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_QUAD;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
|
|
||||||
} else {
|
|
||||||
Log.v(TAG, "Requested " + desiredChannels + " channels, getting 5.1 surround");
|
|
||||||
desiredChannels = 6;
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.v(TAG, "Requested " + desiredChannels + " channels, getting stereo");
|
|
||||||
desiredChannels = 2;
|
|
||||||
channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Log.v(TAG, "Speaker configuration (and order of channels):");
|
|
||||||
|
|
||||||
if ((channelConfig & 0x00000004) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_FRONT_LEFT");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000008) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_FRONT_RIGHT");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000010) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_FRONT_CENTER");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000020) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_LOW_FREQUENCY");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000040) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_BACK_LEFT");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000080) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_BACK_RIGHT");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000100) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_FRONT_LEFT_OF_CENTER");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000200) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_FRONT_RIGHT_OF_CENTER");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000400) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_BACK_CENTER");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00000800) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_SIDE_LEFT");
|
|
||||||
}
|
|
||||||
if ((channelConfig & 0x00001000) != 0) {
|
|
||||||
Log.v(TAG, " CHANNEL_OUT_SIDE_RIGHT");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
frameSize = (sampleSize * desiredChannels);
|
|
||||||
|
|
||||||
// Let the user pick a larger buffer if they really want -- but ye
|
|
||||||
// gods they probably shouldn't, the minimums are horrifyingly high
|
|
||||||
// latency already
|
|
||||||
int minBufferSize;
|
|
||||||
if (isCapture) {
|
|
||||||
minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
|
|
||||||
} else {
|
|
||||||
minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);
|
|
||||||
}
|
|
||||||
desiredFrames = Math.max(desiredFrames, (minBufferSize + frameSize - 1) / frameSize);
|
|
||||||
|
|
||||||
int[] results = new int[4];
|
|
||||||
|
|
||||||
if (isCapture) {
|
|
||||||
if (mAudioRecord == null) {
|
|
||||||
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate,
|
|
||||||
channelConfig, audioFormat, desiredFrames * frameSize);
|
|
||||||
|
|
||||||
// see notes about AudioTrack state in audioOpen(), above. Probably also applies here.
|
|
||||||
if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
|
|
||||||
Log.e(TAG, "Failed during initialization of AudioRecord");
|
|
||||||
mAudioRecord.release();
|
|
||||||
mAudioRecord = null;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
mAudioRecord.startRecording();
|
|
||||||
}
|
|
||||||
|
|
||||||
results[0] = mAudioRecord.getSampleRate();
|
|
||||||
results[1] = mAudioRecord.getAudioFormat();
|
|
||||||
results[2] = mAudioRecord.getChannelCount();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (mAudioTrack == null) {
|
|
||||||
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
|
|
||||||
|
|
||||||
// Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
|
|
||||||
// Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
|
|
||||||
// Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
|
|
||||||
if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
|
|
||||||
/* Try again, with safer values */
|
|
||||||
|
|
||||||
Log.e(TAG, "Failed during initialization of Audio Track");
|
|
||||||
mAudioTrack.release();
|
|
||||||
mAudioTrack = null;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
mAudioTrack.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
results[0] = mAudioTrack.getSampleRate();
|
|
||||||
results[1] = mAudioTrack.getAudioFormat();
|
|
||||||
results[2] = mAudioTrack.getChannelCount();
|
|
||||||
}
|
|
||||||
results[3] = desiredFrames;
|
|
||||||
|
|
||||||
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", got " + results[3] + " frames of " + results[2] + " channel " + getAudioFormatString(results[1]) + " audio at " + results[0] + " Hz");
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
|
|
||||||
return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void audioWriteFloatBuffer(float[] buffer) {
|
|
||||||
if (mAudioTrack == null) {
|
|
||||||
Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < buffer.length;) {
|
|
||||||
int result = mAudioTrack.write(buffer, i, buffer.length - i, AudioTrack.WRITE_BLOCKING);
|
|
||||||
if (result > 0) {
|
|
||||||
i += result;
|
|
||||||
} else if (result == 0) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(1);
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
// Nom nom
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "SDL audio: error return from write(float)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void audioWriteShortBuffer(short[] buffer) {
|
|
||||||
if (mAudioTrack == null) {
|
|
||||||
Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < buffer.length;) {
|
|
||||||
int result = mAudioTrack.write(buffer, i, buffer.length - i);
|
|
||||||
if (result > 0) {
|
|
||||||
i += result;
|
|
||||||
} else if (result == 0) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(1);
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
// Nom nom
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "SDL audio: error return from write(short)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void audioWriteByteBuffer(byte[] buffer) {
|
|
||||||
if (mAudioTrack == null) {
|
|
||||||
Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < buffer.length; ) {
|
|
||||||
int result = mAudioTrack.write(buffer, i, buffer.length - i);
|
|
||||||
if (result > 0) {
|
|
||||||
i += result;
|
|
||||||
} else if (result == 0) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(1);
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
// Nom nom
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "SDL audio: error return from write(byte)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
|
|
||||||
return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This method is called by SDL using JNI. */
|
|
||||||
public static int captureReadFloatBuffer(float[] buffer, boolean blocking) {
|
|
||||||
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This method is called by SDL using JNI. */
|
|
||||||
public static int captureReadShortBuffer(short[] buffer, boolean blocking) {
|
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
|
||||||
return mAudioRecord.read(buffer, 0, buffer.length);
|
|
||||||
} else {
|
|
||||||
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This method is called by SDL using JNI. */
|
|
||||||
public static int captureReadByteBuffer(byte[] buffer, boolean blocking) {
|
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
|
||||||
return mAudioRecord.read(buffer, 0, buffer.length);
|
|
||||||
} else {
|
|
||||||
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This method is called by SDL using JNI. */
|
|
||||||
public static void audioClose() {
|
|
||||||
if (mAudioTrack != null) {
|
|
||||||
mAudioTrack.stop();
|
|
||||||
mAudioTrack.release();
|
|
||||||
mAudioTrack = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This method is called by SDL using JNI. */
|
|
||||||
public static void captureClose() {
|
|
||||||
if (mAudioRecord != null) {
|
|
||||||
mAudioRecord.stop();
|
|
||||||
mAudioRecord.release();
|
|
||||||
mAudioRecord = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This method is called by SDL using JNI. */
|
|
||||||
public static void audioSetThreadPriority(boolean iscapture, int device_id) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
/* Set thread name */
|
|
||||||
if (iscapture) {
|
|
||||||
Thread.currentThread().setName("SDLAudioC" + device_id);
|
|
||||||
} else {
|
|
||||||
Thread.currentThread().setName("SDLAudioP" + device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set thread priority */
|
|
||||||
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.v(TAG, "modify thread properties failed " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static native int nativeSetupJNI();
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.VibrationEffect;
|
|
||||||
import android.os.Vibrator;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.InputDevice;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
|
|
||||||
public class SDLControllerManager {
|
|
||||||
|
|
||||||
public static native int nativeSetupJNI();
|
|
||||||
|
|
||||||
public static native int nativeAddJoystick(int device_id, String name, String desc,
|
|
||||||
int vendor_id, int product_id,
|
|
||||||
boolean is_accelerometer, int button_mask,
|
|
||||||
int naxes, int nhats, int nballs);
|
|
||||||
public static native int nativeRemoveJoystick(int device_id);
|
|
||||||
public static native int nativeAddHaptic(int device_id, String name);
|
|
||||||
public static native int nativeRemoveHaptic(int device_id);
|
|
||||||
public static native int onNativePadDown(int device_id, int keycode);
|
|
||||||
public static native int onNativePadUp(int device_id, int keycode);
|
|
||||||
public static native void onNativeJoy(int device_id, int axis,
|
|
||||||
float value);
|
|
||||||
public static native void onNativeHat(int device_id, int hat_id,
|
|
||||||
int x, int y);
|
|
||||||
|
|
||||||
private static final String TAG = "SDLControllerManager";
|
|
||||||
|
|
||||||
public static void initialize() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
|
|
||||||
public static boolean handleJoystickMotionEvent(MotionEvent event) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void pollInputDevices() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void pollHapticDevices() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void hapticRun(int device_id, float intensity, int length) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
public static void hapticStop(int device_id){
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if a given device is considered a possible SDL joystick
|
|
||||||
public static boolean isDeviceSDLJoystick(int deviceId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SDLJoystickHandler {
|
|
||||||
/**
|
|
||||||
* Handles given MotionEvent.
|
|
||||||
* @param event the event to be handled.
|
|
||||||
* @return if given event was processed.
|
|
||||||
*/
|
|
||||||
public boolean handleMotionEvent(MotionEvent event) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles adding and removing of input devices.
|
|
||||||
*/
|
|
||||||
public void pollInputDevices() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
package org.screwyoyo.faudiogms;
|
|
||||||
|
|
||||||
import java.lang.String;
|
|
||||||
|
|
||||||
public class FAudioGMSNative
|
|
||||||
{
|
|
||||||
public FAudioGMSNative()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exactly as in FAudioGMS_JNI.c: */
|
|
||||||
public native double FAudioGMS_Init(double spatialDistanceScale, double timestep);
|
|
||||||
|
|
||||||
public native double FAudioGMS_StaticSound_LoadWAV(
|
|
||||||
String filePath); /* returns a static sound ID */
|
|
||||||
public native double FAudioGMS_StaticSound_CreateSoundInstance(
|
|
||||||
double staticSoundID); /* returns a sound instance ID */
|
|
||||||
public native double FAudioGMS_StaticSound_Destroy(double staticSoundID);
|
|
||||||
|
|
||||||
/* returns a sound instance ID */
|
|
||||||
public native double FAudioGMS_StreamingSound_LoadOGG(
|
|
||||||
String filepath,
|
|
||||||
double bufferSizeInBytes); /* if 0 is passed we will use a sensible default*/
|
|
||||||
|
|
||||||
public native double FAudioGMS_SoundInstance_Play(double soundInstanceID);
|
|
||||||
public native double FAudioGMS_SoundInstance_Pause(double soundInstanceID);
|
|
||||||
public native double FAudioGMS_SoundInstance_Stop(double soundInstanceID);
|
|
||||||
|
|
||||||
public native double FAudioGMS_SoundInstance_QueueSyncPlay(double soundInstanceID);
|
|
||||||
public native double FAudioGMS_SoundInstance_SyncPlay();
|
|
||||||
|
|
||||||
public native double FAudioGMS_SoundInstance_SetPlayRegion(
|
|
||||||
double soundInstanceID,
|
|
||||||
double startInMilliseconds,
|
|
||||||
double endInMilliseconds);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetLoop(double soundInstanceID, double loop);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume);
|
|
||||||
public native double FAudioGMS_SoundInstance_Set3DPosition(
|
|
||||||
double soundInstanceID,
|
|
||||||
double x,
|
|
||||||
double y,
|
|
||||||
double z);
|
|
||||||
public native double FAudioGMS_SoundInstance_Set3DVelocity(
|
|
||||||
double soundInstanceID,
|
|
||||||
double xVelocity,
|
|
||||||
double yVelocity,
|
|
||||||
double zVelocity);
|
|
||||||
public native double FAudioGMS_SoundInstance_Set3DOrientation(
|
|
||||||
double soundInstanceID,
|
|
||||||
double xFront,
|
|
||||||
double yFront,
|
|
||||||
double zFront,
|
|
||||||
double xTop,
|
|
||||||
double yTop,
|
|
||||||
double zTop);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetTrackPositionInSeconds(
|
|
||||||
double soundInstanceID,
|
|
||||||
double trackPositionInSeconds);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetVolumeOverTime(
|
|
||||||
double soundInstanceID,
|
|
||||||
double volume,
|
|
||||||
double milliseconds);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetLowPassFilter(
|
|
||||||
double soundInstanceID,
|
|
||||||
double lowPassFilter,
|
|
||||||
double Q);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetHighPassFilter(
|
|
||||||
double soundInstanceID,
|
|
||||||
double highPassFilter,
|
|
||||||
double Q);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetBandPassFilter(
|
|
||||||
double soundInstanceID,
|
|
||||||
double bandPassFilter,
|
|
||||||
double Q);
|
|
||||||
|
|
||||||
public native double FAudioGMS_SoundInstance_QueueSoundInstance(
|
|
||||||
double soundInstanceID,
|
|
||||||
double queueSoundInstanceID);
|
|
||||||
|
|
||||||
public native double FAudioGMS_SoundInstance_GetPitch(double soundInstanceID);
|
|
||||||
public native double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID);
|
|
||||||
public native double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double soundInstanceID);
|
|
||||||
public native double FAudioGMS_SoundInstance_GetTrackPositionInSeconds(double soundInstanceID);
|
|
||||||
|
|
||||||
public native double FAudioGMS_SoundInstance_Destroy(double soundInstanceID);
|
|
||||||
public native double FAudioGMS_SoundInstance_DestroyWhenFinished(double soundInstanceID);
|
|
||||||
|
|
||||||
public native double FAudioGMS_EffectChain_Create();
|
|
||||||
public native double FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID);
|
|
||||||
public native double FAudioGMS_EffectChain_AddReverb(
|
|
||||||
double effectChainID,
|
|
||||||
double wetDryMix,
|
|
||||||
double reflectionsDelay,
|
|
||||||
double reverbDelay,
|
|
||||||
double earlyDiffusion,
|
|
||||||
double lateDiffusion,
|
|
||||||
double lowEQGain,
|
|
||||||
double lowEQCutoff,
|
|
||||||
double highEQGain,
|
|
||||||
double highEQCutoff,
|
|
||||||
double reflectionsGain,
|
|
||||||
double reverbGain,
|
|
||||||
double decayTime,
|
|
||||||
double density,
|
|
||||||
double roomSize);
|
|
||||||
public native double FAudioGMS_EffectChain_Destroy(double effectChainID);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: Any changes to the effect chain will NOT apply after this is set!
|
|
||||||
* You MUST call SetEffectChain again if you make changes to the effect
|
|
||||||
* chain parameters!
|
|
||||||
*/
|
|
||||||
public native double FAudioGMS_SoundInstance_SetEffectChain(
|
|
||||||
double soundInstanceID,
|
|
||||||
double effectChainID,
|
|
||||||
double effectGain);
|
|
||||||
public native double FAudioGMS_SoundInstance_SetEffectGain(
|
|
||||||
double soundInstanceID,
|
|
||||||
double effectGain);
|
|
||||||
|
|
||||||
public native double FAudioGMS_SetMasteringEffectChain(double effectChainID, double effectGain);
|
|
||||||
public native double FAudioGMS_SetMasteringEffectGain(double effectGain);
|
|
||||||
|
|
||||||
public native double FAudioGMS_SetListenerPosition(double x, double y, double z);
|
|
||||||
public native double FAudioGMS_SetListenerVelocity(
|
|
||||||
double xVelocity,
|
|
||||||
double yVelocity,
|
|
||||||
double zVelocity);
|
|
||||||
public native double FAudioGMS_SetListenerOrientation(
|
|
||||||
double xFront,
|
|
||||||
double yFront,
|
|
||||||
double zFront,
|
|
||||||
double xTop,
|
|
||||||
double yTop,
|
|
||||||
double zTop);
|
|
||||||
|
|
||||||
public native double FAudioGMS_PauseAll(); /* useful for mobile platforms, etc
|
|
||||||
*/
|
|
||||||
public native double FAudioGMS_ResumeAll(); /* same as above */
|
|
||||||
public native double FAudioGMS_StopAll();
|
|
||||||
|
|
||||||
public native double FAudioGMS_Update();
|
|
||||||
public native double FAudioGMS_Destroy();
|
|
||||||
}
|
|
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/arm64-v8a/libFAudioGMS.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/arm64-v8a/libFAudioGMS.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/arm64-v8a/libSDL2.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/arm64-v8a/libSDL2.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/arm64-v8a/libhidapi.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/arm64-v8a/libhidapi.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/armeabi-v7a/libFAudioGMS.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/armeabi-v7a/libFAudioGMS.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/armeabi-v7a/libSDL2.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/armeabi-v7a/libSDL2.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/armeabi-v7a/libhidapi.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/armeabi-v7a/libhidapi.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86/libFAudioGMS.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86/libFAudioGMS.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86/libSDL2.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86/libSDL2.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86/libhidapi.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86/libhidapi.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86_64/libFAudioGMS.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86_64/libFAudioGMS.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86_64/libSDL2.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86_64/libSDL2.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86_64/libhidapi.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/AndroidSource/libs/x86_64/libhidapi.so (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,7 @@
|
||||||
"options": [],
|
"options": [],
|
||||||
"exportToGame": true,
|
"exportToGame": true,
|
||||||
"supportedTargets": -1,
|
"supportedTargets": -1,
|
||||||
"extensionVersion": "0.3.0",
|
"extensionVersion": "0.2.0",
|
||||||
"packageId": "",
|
"packageId": "",
|
||||||
"productId": "",
|
"productId": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
"helpfile": "",
|
"helpfile": "",
|
||||||
"iosProps": false,
|
"iosProps": false,
|
||||||
"tvosProps": false,
|
"tvosProps": false,
|
||||||
"androidProps": true,
|
"androidProps": false,
|
||||||
"installdir": "",
|
"installdir": "",
|
||||||
"files": [
|
"files": [
|
||||||
{"filename":"FAudioGMS.dll","origname":"","init":"","final":"","kind":1,"uncompress":false,"functions":[
|
{"filename":"FAudioGMS.dll","origname":"","init":"","final":"","kind":1,"uncompress":false,"functions":[
|
||||||
|
@ -25,7 +25,8 @@
|
||||||
{"externalName":"FAudioGMS_StaticSound_LoadWAV","kind":1,"help":"FAudioGMS_StaticSound_LoadWAV(filePath)","hidden":false,"returnType":2,"argCount":0,"args":[
|
{"externalName":"FAudioGMS_StaticSound_LoadWAV","kind":1,"help":"FAudioGMS_StaticSound_LoadWAV(filePath)","hidden":false,"returnType":2,"argCount":0,"args":[
|
||||||
1,
|
1,
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_StaticSound_LoadWAV","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_StaticSound_LoadWAV","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_SoundInstance_Play","kind":1,"help":"FAudioGMS_SoundInstance_Play(id)","hidden":false,"returnType":2,"argCount":0,"args":[
|
{"externalName":"FAudioGMS_SoundInstance_Play","kind":1,"help":"FAudioGMS_SoundInstance_Play(id, loop)","hidden":false,"returnType":2,"argCount":0,"args":[
|
||||||
|
2,
|
||||||
2,
|
2,
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_Play","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_Play","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_SoundInstance_Pause","kind":1,"help":"FAudioGMS_SoundInstance_Pause(id)","hidden":false,"returnType":2,"argCount":0,"args":[
|
{"externalName":"FAudioGMS_SoundInstance_Pause","kind":1,"help":"FAudioGMS_SoundInstance_Pause(id)","hidden":false,"returnType":2,"argCount":0,"args":[
|
||||||
|
@ -55,9 +56,8 @@
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SetListenerPosition","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_SetListenerPosition","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_StreamingSound_LoadOGG","kind":1,"help":"FAudioGMS_StreamingSound_LoadOGG(filePath, bufferSizeInBytes)","hidden":false,"returnType":2,"argCount":0,"args":[
|
{"externalName":"FAudioGMS_StreamingSound_LoadOGG","kind":1,"help":"FAudioGMS_StreamingSound_LoadOGG(filePath)","hidden":false,"returnType":2,"argCount":0,"args":[
|
||||||
1,
|
1,
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_StreamingSound_LoadOGG","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_StreamingSound_LoadOGG","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_SoundInstance_SetPan","kind":1,"help":"FAudioGMS_SoundInstance_SetPan(soundInstanceID, pan)","hidden":false,"returnType":2,"argCount":0,"args":[
|
{"externalName":"FAudioGMS_SoundInstance_SetPan","kind":1,"help":"FAudioGMS_SoundInstance_SetPan(soundInstanceID, pan)","hidden":false,"returnType":2,"argCount":0,"args":[
|
||||||
2,
|
2,
|
||||||
|
@ -77,10 +77,10 @@
|
||||||
2,
|
2,
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetVolumeOverTime","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetVolumeOverTime","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_StopAll","kind":1,"help":"FAudioGMS_StopAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_StopAll","tags":[],"resourceType":"GMExtensionFunction",},
|
{"externalName":"FAudioGMS_StopAll","kind":1,"help":"FAudioGMS_StopAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_StopAll","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_SoundInstance_SetTrackPositionInSeconds","kind":1,"help":"FAudioGMS_SoundInstance_SetTrackPositionInSeconds(soundInstanceID, trackPositionInSeconds)","hidden":false,"returnType":2,"argCount":0,"args":[
|
{"externalName":"FAudioGMS_SoundInstance_SetTrackPosition","kind":1,"help":"FAudioGMS_SoundInstance_SetTrackPosition(soundInstanceID, trackPositionInSeconds)","hidden":false,"returnType":2,"argCount":0,"args":[
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetTrackPositionInSeconds","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetTrackPosition","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","kind":1,"help":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds(soundInstanceID)","hidden":false,"returnType":2,"argCount":0,"args":[
|
{"externalName":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","kind":1,"help":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds(soundInstanceID)","hidden":false,"returnType":2,"argCount":0,"args":[
|
||||||
2,
|
2,
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
|
@ -155,54 +155,7 @@
|
||||||
2,
|
2,
|
||||||
2,
|
2,
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SetListenerVelocity","tags":[],"resourceType":"GMExtensionFunction",},
|
],"resourceVersion":"1.0","name":"FAudioGMS_SetListenerVelocity","tags":[],"resourceType":"GMExtensionFunction",},
|
||||||
{"externalName":"FAudioGMS_PauseAll","kind":1,"help":"FAudioGMS_PauseAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_PauseAll","tags":[],"resourceType":"GMExtensionFunction",},
|
],"constants":[],"ProxyFiles":[],"copyToTargets":64,"order":[
|
||||||
{"externalName":"FAudioGMS_ResumeAll","kind":1,"help":"FAudioGMS_ResumeAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_ResumeAll","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SoundInstance_SetPlayRegion","kind":1,"help":"FAudioGMS_SoundInstance_SetPlayRegion(soundInstanceID, startInMilliseconds, endInMilliseconds)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetPlayRegion","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SetMasteringEffectChain","kind":1,"help":"FAudioGMS_SetMasteringEffectChain(effectChainID, effectGain)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SetMasteringEffectChain","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SetMasteringEffectGain","kind":1,"help":"FAudioGMS_SetMasteringEffectGain(effectGain)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SetMasteringEffectGain","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SoundInstance_SetLoop","kind":1,"help":"FAudioGMS_SoundInstance_SetLoop(soundInstanceID, loop)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetLoop","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SoundInstance_QueueSoundInstance","kind":1,"help":"FAudioGMS_SoundInstance_QueueSoundInstance(soundInstanceID, queueSoundInstanceID)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_QueueSoundInstance","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SoundInstance_QueueSyncPlay","kind":1,"help":"FAudioGMS_SoundInstance_QueueSyncPlay(soundInstanceID)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_QueueSyncPlay","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SoundInstance_SyncPlay","kind":1,"help":"FAudioGMS_SoundInstance_SyncPlay()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SyncPlay","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SoundInstance_Set3DOrientation","kind":1,"help":"FAudioGMS_SoundInstance_Set3DOrientation(soundInstanceID, xFront, yFront, zFront, xTop, yTop, zTop)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_Set3DOrientation","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
{"externalName":"FAudioGMS_SetListenerOrientation","kind":1,"help":"FAudioGMS_SetListenerOrientation(xFront, yFront, zFront, xTop, yTop, zTop)","hidden":false,"returnType":2,"argCount":0,"args":[
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
],"resourceVersion":"1.0","name":"FAudioGMS_SetListenerOrientation","tags":[],"resourceType":"GMExtensionFunction",},
|
|
||||||
],"constants":[],"ProxyFiles":[
|
|
||||||
{"TargetMask":7,"resourceVersion":"1.0","name":"libFAudioGMS.so","tags":[],"resourceType":"GMProxyFile",},
|
|
||||||
{"TargetMask":3,"resourceVersion":"1.0","name":"FAudioGMSAndroidDummy.ext","tags":[],"resourceType":"GMProxyFile",},
|
|
||||||
{"TargetMask":7,"resourceVersion":"1.0","name":"libSDL2-2.0.so.0","tags":[],"resourceType":"GMProxyFile",},
|
|
||||||
],"copyToTargets":200,"order":[
|
|
||||||
{"name":"FAudioGMS_Init","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_Init","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_StaticSound_LoadWAV","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_StaticSound_LoadWAV","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_StaticSound_CreateSoundInstance","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_StaticSound_CreateSoundInstance","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
|
@ -211,17 +164,12 @@
|
||||||
{"name":"FAudioGMS_SoundInstance_Play","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_Play","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_Pause","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_Pause","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_Stop","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_Stop","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_QueueSyncPlay","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SoundInstance_SyncPlay","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SoundInstance_SetLoop","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SoundInstance_SetPan","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetPan","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_SetPitch","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetPitch","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_SetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_Set3DPosition","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_Set3DPosition","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_Set3DVelocity","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_Set3DVelocity","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_Set3DOrientation","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetTrackPosition","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_SetTrackPositionInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SoundInstance_SetPlayRegion","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SoundInstance_SetVolumeOverTime","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetVolumeOverTime","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_SetLowPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetLowPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_SetHighPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetHighPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
|
@ -230,7 +178,6 @@
|
||||||
{"name":"FAudioGMS_SoundInstance_GetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_GetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_GetTrackPositionInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_GetTrackPositionInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_QueueSoundInstance","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SoundInstance_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_DestroyWhenFinished","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_DestroyWhenFinished","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_EffectChain_Create","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_EffectChain_Create","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
|
@ -239,13 +186,8 @@
|
||||||
{"name":"FAudioGMS_EffectChain_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_EffectChain_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_SetEffectChain","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetEffectChain","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SoundInstance_SetEffectGain","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SoundInstance_SetEffectGain","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SetMasteringEffectChain","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SetMasteringEffectGain","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_SetListenerPosition","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SetListenerPosition","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SetListenerVelocity","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_SetListenerVelocity","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_SetListenerOrientation","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_ResumeAll","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_PauseAll","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
|
||||||
{"name":"FAudioGMS_StopAll","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_StopAll","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_Update","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_Update","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
{"name":"FAudioGMS_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
{"name":"FAudioGMS_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",},
|
||||||
|
@ -255,7 +197,7 @@
|
||||||
"tvosclassname": null,
|
"tvosclassname": null,
|
||||||
"tvosdelegatename": null,
|
"tvosdelegatename": null,
|
||||||
"iosdelegatename": "",
|
"iosdelegatename": "",
|
||||||
"androidclassname": "FAudioGMSBridge",
|
"androidclassname": "",
|
||||||
"sourcedir": "",
|
"sourcedir": "",
|
||||||
"androidsourcedir": "",
|
"androidsourcedir": "",
|
||||||
"macsourcedir": "",
|
"macsourcedir": "",
|
||||||
|
@ -279,7 +221,7 @@
|
||||||
"tvosThirdPartyFrameworkEntries": [],
|
"tvosThirdPartyFrameworkEntries": [],
|
||||||
"IncludedResources": [],
|
"IncludedResources": [],
|
||||||
"androidPermissions": [],
|
"androidPermissions": [],
|
||||||
"copyToTargets": 200,
|
"copyToTargets": 64,
|
||||||
"iosCocoaPods": "",
|
"iosCocoaPods": "",
|
||||||
"tvosCocoaPods": "",
|
"tvosCocoaPods": "",
|
||||||
"iosCocoaPodDependencies": "",
|
"iosCocoaPodDependencies": "",
|
||||||
|
|
BIN
gamemaker/extensions/FAudioGMS/libFAudioGMS.so (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/libFAudioGMS.so (Stored with Git LFS)
Binary file not shown.
BIN
gamemaker/extensions/FAudioGMS/libSDL2-2.0.so.0 (Stored with Git LFS)
BIN
gamemaker/extensions/FAudioGMS/libSDL2-2.0.so.0 (Stored with Git LFS)
Binary file not shown.
|
@ -1,17 +1 @@
|
||||||
/// @description Clean up all resources when the game is about to end.
|
|
||||||
|
|
||||||
/* Destroy sound instances first: */
|
|
||||||
// sndInst.Stop();
|
|
||||||
// sndInst.Destroy();
|
|
||||||
// sndInst = undefined;
|
|
||||||
|
|
||||||
/* Only then destroy static sounds: */
|
|
||||||
// snd.Destroy();
|
|
||||||
// snd = undefined;
|
|
||||||
|
|
||||||
/* And only then, destroy effect chains */
|
|
||||||
effChain.Destroy();
|
|
||||||
effChain = undefined;
|
|
||||||
|
|
||||||
/* Finish up the system */
|
|
||||||
FAudioGMS_Destroy();
|
FAudioGMS_Destroy();
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
/// @description Initialize audio.
|
|
||||||
|
|
||||||
/* First initialize the system: */
|
|
||||||
var spatialDistanceScale = 50; // makes "3D" audio louder
|
var spatialDistanceScale = 50; // makes "3D" audio louder
|
||||||
var timestep = game_get_speed(gamespeed_microseconds) / 1000000; // default, autodetect from GM timestep.
|
FAudioGMS_Init(spatialDistanceScale, 1 / 60);
|
||||||
FAudioGMS_Init(spatialDistanceScale, timestep);
|
|
||||||
|
|
||||||
/* Init Effects Chains Here */
|
/* Init Effects Chains Here */
|
||||||
effChain = new EffectChain();
|
|
||||||
effChain.AddDefaultReverb();
|
|
||||||
|
|
||||||
/* Load Audio Assets Here */
|
/* Load Audio Assets Here */
|
||||||
// snd = LoadStaticSound("go-go-go-tigerblood.wav");
|
|
||||||
// sndInst = snd.Play();
|
|
||||||
// sndInst.SetEffectChain(effChain, 1); // apply default reverb to the instance.
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
/// @description MUST be called once per frame!
|
|
||||||
FAudioGMS_Update();
|
FAudioGMS_Update();
|
|
@ -1,16 +1,9 @@
|
||||||
// working_directory on android is "assets/" which makes SDL freak out.
|
|
||||||
function GetPathPrepend()
|
|
||||||
{
|
|
||||||
if (os_type != os_android) return working_directory;
|
|
||||||
else return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticSounds are usually short and intended to be played multiple times.
|
// StaticSounds are usually short and intended to be played multiple times.
|
||||||
// All of the sound data lives in memory for as long as the StaticSound exists.
|
// All of the sound data lives in memory for as long as the StaticSound exists.
|
||||||
// Playing a StaticSound returns a SoundInstance.
|
// Playing a StaticSound returns a SoundInstance.
|
||||||
function LoadStaticSound(filename)
|
function LoadStaticSound(filename)
|
||||||
{
|
{
|
||||||
var filePath = GetPathPrepend() + "audio/static/" + filename;
|
var filePath = "audio\\static\\" + filename;
|
||||||
var staticSoundID = FAudioGMS_StaticSound_LoadWAV(filePath);
|
var staticSoundID = FAudioGMS_StaticSound_LoadWAV(filePath);
|
||||||
return new StaticSound(staticSoundID);
|
return new StaticSound(staticSoundID);
|
||||||
}
|
}
|
||||||
|
@ -19,29 +12,16 @@ function StaticSound(_staticSoundID) constructor
|
||||||
{
|
{
|
||||||
staticSoundID = _staticSoundID;
|
staticSoundID = _staticSoundID;
|
||||||
|
|
||||||
// Create a sound instance from this static sound.
|
// Returns a sound instance!
|
||||||
static CreateSoundInstance = function()
|
|
||||||
{
|
|
||||||
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
|
|
||||||
var instance = new SoundInstance(instanceID);
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plays and returns a sound instance!
|
|
||||||
// MUST be destroyed when you aren't referencing it any more or you will leak memory!
|
// MUST be destroyed when you aren't referencing it any more or you will leak memory!
|
||||||
static Play = function(pan = 0, pitch = 1, volume = 1, loop = false, loopStartInMilliseconds = 0, loopEndInMilliseconds = 0)
|
static Play = function(pan = 0, pitch = 1, volume = 1, loop = false)
|
||||||
{
|
{
|
||||||
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
|
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
|
||||||
var instance = new SoundInstance(instanceID);
|
var instance = new SoundInstance(instanceID);
|
||||||
instance.SetLoop(loop);
|
|
||||||
if (loop)
|
|
||||||
{
|
|
||||||
instance.SetPlayRegion(loopStartInMilliseconds, loopEndInMilliseconds);
|
|
||||||
}
|
|
||||||
instance.SetPan(pan);
|
instance.SetPan(pan);
|
||||||
instance.SetPitch(pitch);
|
instance.SetPitch(pitch);
|
||||||
instance.SetVolume(volume);
|
instance.SetVolume(volume);
|
||||||
instance.Play();
|
instance.Play(loop);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +33,12 @@ function StaticSound(_staticSoundID) constructor
|
||||||
instance.DestroyWhenFinished();
|
instance.DestroyWhenFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plays and returns a sound instance!
|
// Returns a sound instance!
|
||||||
// MUST be destroyed when you aren't referencing it any more or you will leak memory!
|
// MUST be destroyed when you aren't referencing it any more or you will leak memory!
|
||||||
static PlaySpatial = function(xPosition, yPosition, zPosition, pitch = 1, volume = 1, loop = false)
|
static PlaySpatial = function(xPosition, yPosition, zPosition, pitch = 1, volume = 1, loop = false)
|
||||||
{
|
{
|
||||||
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
|
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
|
||||||
var instance = new SoundInstance(instanceID);
|
var instance = new SoundInstance(instanceID);
|
||||||
instance.SetLoop(loop);
|
|
||||||
instance.Set3DPosition(xPosition, yPosition, zPosition);
|
instance.Set3DPosition(xPosition, yPosition, zPosition);
|
||||||
instance.SetPitch(pitch);
|
instance.SetPitch(pitch);
|
||||||
instance.SetVolume(volume);
|
instance.SetVolume(volume);
|
||||||
|
@ -88,10 +67,10 @@ function StaticSound(_staticSoundID) constructor
|
||||||
// The audio is streamed off the disk, so only a small amount of memory is used at a time.
|
// The audio is streamed off the disk, so only a small amount of memory is used at a time.
|
||||||
// Good for things like music or voiceover playback.
|
// Good for things like music or voiceover playback.
|
||||||
// Note that StreamingSounds are SoundInstances.
|
// Note that StreamingSounds are SoundInstances.
|
||||||
function LoadStreamingSound(filename, bufferSizeInBytes = 0)
|
function LoadStreamingSound(filename)
|
||||||
{
|
{
|
||||||
var filePath = GetPathPrepend() + "audio/streaming/" + filename;
|
var filePath = "audio\\streaming\\" + filename;
|
||||||
soundInstanceID = FAudioGMS_StreamingSound_LoadOGG(filePath, bufferSizeInBytes);
|
soundInstanceID = FAudioGMS_StreamingSound_LoadOGG(filePath);
|
||||||
return new SoundInstance(soundInstanceID);
|
return new SoundInstance(soundInstanceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +79,9 @@ function SoundInstance(_soundInstanceID) constructor
|
||||||
soundInstanceID = _soundInstanceID;
|
soundInstanceID = _soundInstanceID;
|
||||||
|
|
||||||
// Plays the sound or resumes from pause.
|
// Plays the sound or resumes from pause.
|
||||||
static Play = function()
|
static Play = function(loop = false)
|
||||||
{
|
{
|
||||||
FAudioGMS_SoundInstance_Play(soundInstanceID);
|
FAudioGMS_SoundInstance_Play(soundInstanceID, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pauses playback.
|
// Pauses playback.
|
||||||
|
@ -129,18 +108,6 @@ function SoundInstance(_soundInstanceID) constructor
|
||||||
FAudioGMS_SoundInstance_Set3DVelocity(soundInstanceID, xVelocity, yVelocity, zVelocity);
|
FAudioGMS_SoundInstance_Set3DVelocity(soundInstanceID, xVelocity, yVelocity, zVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the 3-dimensional orientation of the sound.
|
|
||||||
static Set3DOrientation = function(xFront, yFront, zFront, xTop, yTop, zTop)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_Set3DOrientation(soundInstanceID, xFront, yFront, zFront, xTop, yTop, zTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets whether the sound instance loops (true) or does not (false).
|
|
||||||
static SetLoop = function(loop)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetLoop(soundInstanceID, loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the panning value of the sound. -1 is farthest left, 1 is farthest right, 0 is center.
|
// Sets the panning value of the sound. -1 is farthest left, 1 is farthest right, 0 is center.
|
||||||
// NOTE: This is ignored if you have called Set3DPosition.
|
// NOTE: This is ignored if you have called Set3DPosition.
|
||||||
static SetPan = function(pan)
|
static SetPan = function(pan)
|
||||||
|
@ -171,19 +138,7 @@ function SoundInstance(_soundInstanceID) constructor
|
||||||
// Sets the position of track playback.
|
// Sets the position of track playback.
|
||||||
static SetTrackPosition = function(seconds)
|
static SetTrackPosition = function(seconds)
|
||||||
{
|
{
|
||||||
FAudioGMS_SoundInstance_SetTrackPositionInSeconds(soundInstanceID, seconds);
|
FAudioGMS_SoundInstance_SetTrackPosition(soundInstanceID, seconds);
|
||||||
}
|
|
||||||
|
|
||||||
// Queues this sound instance for playing in sync.
|
|
||||||
static QueueSyncPlay = function()
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_QueueSyncPlay(soundInstanceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the playback region for the sound instance.
|
|
||||||
static SetPlayRegion = function(loopStartInMilliseconds, loopEndInMilliseconds)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SetPlayRegion(soundInstanceID, loopStartInMilliseconds, loopEndInMilliseconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets a low pass filter on the sound.
|
// Sets a low pass filter on the sound.
|
||||||
|
@ -226,11 +181,6 @@ function SoundInstance(_soundInstanceID) constructor
|
||||||
FAudioGMS_SoundInstance_SetEffectGain(soundInstanceID, gain);
|
FAudioGMS_SoundInstance_SetEffectGain(soundInstanceID, gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QueueSoundInstance = function(queueSoundInstance)
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_QueueSoundInstance(soundInstanceID, queueSoundInstance.soundInstanceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the pitch of the sound.
|
// Gets the pitch of the sound.
|
||||||
static GetPitch = function()
|
static GetPitch = function()
|
||||||
{
|
{
|
||||||
|
@ -275,12 +225,6 @@ function SoundInstance(_soundInstanceID) constructor
|
||||||
SetVolume(1);
|
SetVolume(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plays the sound instance queue.
|
|
||||||
function SyncPlay()
|
|
||||||
{
|
|
||||||
FAudioGMS_SoundInstance_SyncPlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Effect chains allow you to modify sound playback using audio effects.
|
// Effect chains allow you to modify sound playback using audio effects.
|
||||||
// Right now only reverb is implemented, but more effects will probably come later.
|
// Right now only reverb is implemented, but more effects will probably come later.
|
||||||
function EffectChain() constructor
|
function EffectChain() constructor
|
||||||
|
@ -366,12 +310,6 @@ function SetListenerVelocity(xVelocity, yVelocity, zVelocity)
|
||||||
FAudioGMS_SetListenerVelocity(xVelocity, yVelocity, zVelocity);
|
FAudioGMS_SetListenerVelocity(xVelocity, yVelocity, zVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the orientation of the listener for 3D audio.
|
|
||||||
function SetListenerOrientation(xFront, yFront, zFront, xTop, yTop, zTop)
|
|
||||||
{
|
|
||||||
FAudioGMS_SetListenerOrientation(xFront, yFront, zFront, xTop, yTop, zTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stops all audio playback.
|
// Stops all audio playback.
|
||||||
function StopAllAudio()
|
function StopAllAudio()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit caf9754455b8ad0f6df5d024203940e9b6e3f47e
|
Subproject commit 28528bc885581bad58050517d78848cb206b2aa3
|
File diff suppressed because it is too large
Load Diff
1525
src/FAudioGMS.c
1525
src/FAudioGMS.c
File diff suppressed because it is too large
Load Diff
149
src/FAudioGMS.h
149
src/FAudioGMS.h
|
@ -36,91 +36,43 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_Init(double spatialDistanceScale, double timestep);
|
FAUDIOGMSAPI void FAudioGMS_Init(double spatialDistanceScale, double timestep);
|
||||||
|
|
||||||
FAUDIOGMSAPI double FAudioGMS_StaticSound_LoadWAV(
|
FAUDIOGMSAPI double FAudioGMS_StaticSound_LoadWAV(char *filePath); /* returns a static sound ID */
|
||||||
char *filePath); /* returns a static sound ID */
|
FAUDIOGMSAPI double FAudioGMS_StaticSound_CreateSoundInstance(double staticSoundID); /* returns a sound instance ID */
|
||||||
FAUDIOGMSAPI double FAudioGMS_StaticSound_CreateSoundInstance(
|
FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double staticSoundID);
|
||||||
double staticSoundID); /* returns a sound instance ID */
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double staticSoundID);
|
|
||||||
|
|
||||||
/* returns a sound instance ID */
|
FAUDIOGMSAPI double FAudioGMS_StreamingSound_LoadOGG(char* filepath); /* returns a sound instance ID */
|
||||||
FAUDIOGMSAPI double FAudioGMS_StreamingSound_LoadOGG(
|
|
||||||
char *filepath,
|
|
||||||
double bufferSizeInBytes); /* if 0 is passed we will use a sensible default*/
|
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Play(double soundInstanceID);
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Play(double soundInstanceID, double loop);
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Pause(double soundInstanceID);
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Pause(double soundInstanceID);
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Stop(double soundInstanceID);
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Stop(double soundInstanceID);
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_QueueSyncPlay(double soundInstanceID);
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan);
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SyncPlay();
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DPosition(double soundInstanceID, double x, double y, double z);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DVelocity(double soundInstanceID, double xVelocity, double yVelocity, double zVelocity);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPositionInSeconds(double soundInstanceID, double trackPositionInSeconds);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolumeOverTime(double soundInstanceID, double volume, double milliseconds);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLowPassFilter(double soundInstanceID, double lowPassFilter, double Q);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetHighPassFilter(double soundInstanceID, double highPassFilter, double Q);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, double bandPassFilter, double Q);
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPlayRegion(
|
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetPitch(double soundInstanceID);
|
||||||
double soundInstanceID,
|
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID);
|
||||||
double startInMilliseconds,
|
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double soundInstanceID);
|
||||||
double endInMilliseconds);
|
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackPositionInSeconds(double soundInstanceID);
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLoop(double soundInstanceID, double loop);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DPosition(
|
|
||||||
double soundInstanceID,
|
|
||||||
double x,
|
|
||||||
double y,
|
|
||||||
double z);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DVelocity(
|
|
||||||
double soundInstanceID,
|
|
||||||
double xVelocity,
|
|
||||||
double yVelocity,
|
|
||||||
double zVelocity);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DOrientation(
|
|
||||||
double soundInstanceID,
|
|
||||||
double xFront,
|
|
||||||
double yFront,
|
|
||||||
double zFront,
|
|
||||||
double xTop,
|
|
||||||
double yTop,
|
|
||||||
double zTop);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPositionInSeconds(
|
|
||||||
double soundInstanceID,
|
|
||||||
double trackPositionInSeconds);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolumeOverTime(
|
|
||||||
double soundInstanceID,
|
|
||||||
double volume,
|
|
||||||
double milliseconds);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLowPassFilter(
|
|
||||||
double soundInstanceID,
|
|
||||||
double lowPassFilter,
|
|
||||||
double Q);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetHighPassFilter(
|
|
||||||
double soundInstanceID,
|
|
||||||
double highPassFilter,
|
|
||||||
double Q);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetBandPassFilter(
|
|
||||||
double soundInstanceID,
|
|
||||||
double bandPassFilter,
|
|
||||||
double Q);
|
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_QueueSoundInstance(
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Destroy(double soundInstanceID);
|
||||||
double soundInstanceID,
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_DestroyWhenFinished(double soundInstanceID);
|
||||||
double queueSoundInstanceID);
|
|
||||||
|
|
||||||
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetPitch(double soundInstanceID);
|
FAUDIOGMSAPI double FAudioGMS_EffectChain_Create();
|
||||||
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID);
|
FAUDIOGMSAPI void FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID);
|
||||||
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double soundInstanceID);
|
FAUDIOGMSAPI void FAudioGMS_EffectChain_AddReverb(
|
||||||
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackPositionInSeconds(double soundInstanceID);
|
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Destroy(double soundInstanceID);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_DestroyWhenFinished(double soundInstanceID);
|
|
||||||
|
|
||||||
FAUDIOGMSAPI double FAudioGMS_EffectChain_Create();
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_EffectChain_AddDefaultReverb(double effectChainID);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_EffectChain_AddReverb(
|
|
||||||
double effectChainID,
|
double effectChainID,
|
||||||
double wetDryMix,
|
double wetDryMix,
|
||||||
double reflectionsDelay,
|
double reflectionsDelay,
|
||||||
|
@ -135,45 +87,24 @@ extern "C"
|
||||||
double reverbGain,
|
double reverbGain,
|
||||||
double decayTime,
|
double decayTime,
|
||||||
double density,
|
double density,
|
||||||
double roomSize);
|
double roomSize
|
||||||
FAUDIOGMSAPI void FAudioGMS_EffectChain_Destroy(double effectChainID);
|
);
|
||||||
|
FAUDIOGMSAPI void FAudioGMS_EffectChain_Destroy(double effectChainID);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: Any changes to the effect chain will NOT apply after this is set!
|
* NOTE: Any changes to the effect chain will NOT apply after this is set!
|
||||||
* You MUST call SetEffectChain again if you make changes to the effect
|
* You MUST call SetEffectChain again if you make changes to the effect chain parameters!
|
||||||
* chain parameters!
|
|
||||||
*/
|
*/
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetEffectChain(
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetEffectChain(double soundInstanceID, double effectChainID, double effectGain);
|
||||||
double soundInstanceID,
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetEffectGain(double soundInstanceID, double effectGain);
|
||||||
double effectChainID,
|
|
||||||
double effectGain);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetEffectGain(
|
|
||||||
double soundInstanceID,
|
|
||||||
double effectGain);
|
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SetMasteringEffectChain(double effectChainID, double effectGain);
|
FAUDIOGMSAPI void FAudioGMS_SetListenerPosition(double x, double y, double z);
|
||||||
FAUDIOGMSAPI void FAudioGMS_SetMasteringEffectGain(double effectGain);
|
FAUDIOGMSAPI void FAudioGMS_SetListenerVelocity(double xVelocity, double yVelocity, double zVelocity);
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SetListenerPosition(double x, double y, double z);
|
FAUDIOGMSAPI void FAudioGMS_StopAll();
|
||||||
FAUDIOGMSAPI void FAudioGMS_SetListenerVelocity(
|
|
||||||
double xVelocity,
|
|
||||||
double yVelocity,
|
|
||||||
double zVelocity);
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_SetListenerOrientation(
|
|
||||||
double xFront,
|
|
||||||
double yFront,
|
|
||||||
double zFront,
|
|
||||||
double xTop,
|
|
||||||
double yTop,
|
|
||||||
double zTop);
|
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_PauseAll(); /* useful for mobile platforms, etc
|
FAUDIOGMSAPI void FAudioGMS_Update();
|
||||||
*/
|
FAUDIOGMSAPI void FAudioGMS_Destroy();
|
||||||
FAUDIOGMSAPI void FAudioGMS_ResumeAll(); /* same as above */
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_StopAll();
|
|
||||||
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_Update();
|
|
||||||
FAUDIOGMSAPI void FAudioGMS_Destroy();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,13 @@
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>ClangCL</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<UseOfMfc>false</UseOfMfc>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
@ -90,23 +89,20 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MultiThreaded</RuntimeLibrary>
|
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libucrt.lib;SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;libucrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<ProjectReference>
|
|
||||||
<UseLibraryDependencyInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</UseLibraryDependencyInputs>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\src\FAudioGMS.c" />
|
<ClCompile Include="..\src\FAudioGMS.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\lib\dr_wav.h" />
|
||||||
<ClInclude Include="..\src\FAudioGMS.h" />
|
<ClInclude Include="..\src\FAudioGMS.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue