Merge branch 'master' of ssh://git.axiodl.com:6431/AxioDL/boo

This commit is contained in:
Jack Andersen 2019-08-31 10:34:11 -10:00
commit c642bccf03
101 changed files with 2799 additions and 2369 deletions

View File

@ -5,140 +5,232 @@ cmake_policy(SET CMP0074 NEW)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (NOT MSVC) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-narrowing")
endif()
if (NOT TARGET logvisor) if (NOT TARGET logvisor)
add_subdirectory(logvisor) add_subdirectory(logvisor)
endif() endif()
add_subdirectory(soxr/src)
add_subdirectory(xxhash) add_subdirectory(xxhash)
add_library(boo
lib/audiodev/Common.hpp
lib/audiodev/AudioMatrix.hpp
lib/audiodev/AudioSubmix.cpp
lib/audiodev/AudioSubmix.hpp
lib/audiodev/AudioVoice.cpp
lib/audiodev/AudioVoice.hpp
lib/audiodev/AudioVoiceEngine.cpp
lib/audiodev/AudioVoiceEngine.hpp
lib/audiodev/LtRtProcessing.cpp
lib/audiodev/LtRtProcessing.hpp
lib/audiodev/MIDICommon.cpp
lib/audiodev/MIDICommon.hpp
lib/audiodev/MIDIDecoder.cpp
lib/audiodev/MIDIEncoder.cpp
lib/audiodev/WAVOut.cpp
lib/Common.hpp
lib/graphicsdev/Common.cpp
lib/graphicsdev/Common.hpp
lib/inputdev/DeviceBase.cpp include/boo/inputdev/DeviceBase.hpp
lib/inputdev/CafeProPad.cpp include/boo/inputdev/CafeProPad.hpp
lib/inputdev/RevolutionPad.cpp include/boo/inputdev/RevolutionPad.hpp
lib/inputdev/DolphinSmashAdapter.cpp include/boo/inputdev/DolphinSmashAdapter.hpp
lib/inputdev/NintendoPowerA.cpp include/boo/inputdev/NintendoPowerA.hpp
lib/inputdev/DualshockPad.cpp include/boo/inputdev/DualshockPad.hpp
lib/inputdev/GenericPad.cpp include/boo/inputdev/GenericPad.hpp
lib/inputdev/DeviceSignature.cpp include/boo/inputdev/DeviceSignature.hpp
lib/inputdev/DeviceFinder.cpp include/boo/inputdev/DeviceFinder.hpp
lib/inputdev/HIDParser.cpp include/boo/inputdev/HIDParser.hpp
lib/inputdev/IHIDDevice.hpp
include/boo/IGraphicsContext.hpp
include/boo/audiodev/IAudioSubmix.hpp
include/boo/audiodev/IAudioVoice.hpp
include/boo/audiodev/IAudioVoiceEngine.hpp
include/boo/audiodev/IMIDIPort.hpp
include/boo/audiodev/IMIDIReader.hpp
include/boo/audiodev/MIDIDecoder.hpp
include/boo/audiodev/MIDIEncoder.hpp
include/boo/graphicsdev/IGraphicsDataFactory.hpp
include/boo/graphicsdev/IGraphicsCommandQueue.hpp
include/boo/inputdev/IHIDListener.hpp
include/boo/inputdev/XInputPad.hpp
include/boo/boo.hpp
include/boo/BooObject.hpp
include/boo/DeferredWindowEvents.hpp
include/boo/IApplication.hpp
include/boo/IWindow.hpp
include/boo/System.hpp
include/boo/ThreadLocalPtr.hpp
InputDeviceClasses.cpp
)
if (NOT MSVC)
target_compile_options(boo PRIVATE -Wno-narrowing)
endif()
option(BOO_GRAPHICS_DEBUG_GROUPS "Enable Debug Groups for labeling graphics passes within backend API." OFF) option(BOO_GRAPHICS_DEBUG_GROUPS "Enable Debug Groups for labeling graphics passes within backend API." OFF)
if (BOO_GRAPHICS_DEBUG_GROUPS) if (BOO_GRAPHICS_DEBUG_GROUPS)
message(STATUS "Enabling graphics debug groups") message(STATUS "Enabling graphics debug groups")
list(APPEND _BOO_SYS_DEFINES -DBOO_GRAPHICS_DEBUG_GROUPS=1) target_compile_definitions(boo PUBLIC -DBOO_GRAPHICS_DEBUG_GROUPS=1)
endif() endif()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
find_package(IPP) find_package(IPP)
if (IPP_FOUND) if (IPP_FOUND)
list(APPEND _BOO_SYS_DEFINES -DINTEL_IPP=1) target_compile_definitions(boo PUBLIC -DINTEL_IPP=1)
list(APPEND _BOO_SYS_INCLUDES ${IPP_INCLUDE_DIRS}) target_include_directories(boo PUBLIC ${IPP_INCLUDE_DIRS})
list(APPEND _BOO_SYS_LIBS ${IPP_LIBRARIES}) target_link_libraries(boo PUBLIC ${IPP_LIBRARIES})
message(STATUS "Building with IPP support") message(STATUS "Building with IPP support")
else() else()
message(WARNING "IPP not found; skipping support") message(WARNING "IPP not found; skipping support")
endif () endif ()
add_subdirectory(soxr/src)
set(_EXTRA_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}) set(_EXTRA_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(boo PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
)
add_subdirectory(lib/graphicsdev/nx) add_subdirectory(lib/graphicsdev/nx)
if(TARGET nx_compiler) if(TARGET nx_compiler)
list(APPEND _BOO_SYS_DEFINES -DHECL_NOUVEAU_NX=1) target_compile_definitions(boo PUBLIC -DHECL_NOUVEAU_NX=1)
endif() endif()
if(NOT GEKKO AND NOT CAFE AND NOT WINDOWS_STORE AND NOT NX) if(NOT GEKKO AND NOT CAFE AND NOT WINDOWS_STORE AND NOT NX)
add_library(glew lib/graphicsdev/glew.c) add_library(glew lib/graphicsdev/glew.c)
# For some reason, clang takes forever if glew.c is not built with -Os
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
set_source_files_properties(lib/graphicsdev/glew.c PROPERTIES COMPILE_FLAGS -Os)
endif()
target_include_directories(glew PUBLIC include/boo/graphicsdev) target_include_directories(glew PUBLIC include/boo/graphicsdev)
target_compile_definitions(glew PUBLIC -DGLEW_NO_GLU=1) target_compile_definitions(glew PUBLIC -DGLEW_NO_GLU=1)
endif() endif()
if(NOT GEKKO AND NOT CAFE AND NOT WINDOWS_STORE AND NOT NX AND NOT APPLE) if(NOT GEKKO AND NOT CAFE AND NOT WINDOWS_STORE AND NOT NX AND NOT APPLE)
list(APPEND PLAT_SRCS lib/graphicsdev/GL.cpp) target_sources(boo PRIVATE lib/graphicsdev/GL.cpp)
list(APPEND _BOO_SYS_DEFINES -DBOO_HAS_GL=1) target_compile_definitions(boo PUBLIC -DBOO_HAS_GL=1)
list(APPEND _BOO_SYS_LIBS glew) target_link_libraries(boo PUBLIC glew)
list(APPEND PLAT_HDRS target_sources(boo PRIVATE
include/boo/graphicsdev/GLSLMacros.hpp include/boo/graphicsdev/GL.hpp
include/boo/graphicsdev/GL.hpp include/boo/graphicsdev/GLSLMacros.hpp
include/boo/graphicsdev/Vulkan.hpp include/boo/graphicsdev/Vulkan.hpp
include/boo/graphicsdev/VulkanDispatchTable.hpp) include/boo/graphicsdev/VulkanDispatchTable.hpp
)
endif() endif()
if(WINDOWS_STORE) if(WINDOWS_STORE)
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/win/ApplicationUWP.cpp lib/audiodev/AudioMatrixSSE.cpp
lib/win/WindowUWP.cpp lib/audiodev/WASAPI.cpp
lib/win/WinCommon.hpp lib/inputdev/HIDDeviceUWP.cpp
lib/win/UWPCommon.hpp lib/inputdev/HIDListenerUWP.cpp
lib/inputdev/HIDListenerUWP.cpp lib/graphicsdev/D3D11.cpp
lib/inputdev/HIDDeviceUWP.cpp lib/graphicsdev/D3D12.cpp
lib/graphicsdev/D3D11.cpp lib/win/ApplicationUWP.cpp
lib/graphicsdev/D3D12.cpp lib/win/UWPCommon.hpp
lib/audiodev/WASAPI.cpp lib/win/WinCommon.hpp
lib/audiodev/AudioMatrixSSE.cpp) lib/win/WindowUWP.cpp
list(APPEND PLAT_HDRS include/boo/UWPViewProvider.hpp
include/boo/UWPViewProvider.hpp include/boo/graphicsdev/D3D.hpp
include/boo/graphicsdev/D3D.hpp) )
list(APPEND _BOO_SYS_DEFINES -DUNICODE -D_UNICODE) target_compile_definitions(boo PUBLIC
-DUNICODE
list(APPEND _BOO_SYS_LIBS Winusb opengl32 Setupapi Imm32 Winmm Shlwapi Hid Xinput) -D_UNICODE
)
target_link_libraries(boo PUBLIC
Hid
Imm32
opengl32
Setupapi
Shlwapi
Winmm
Winusb
Xinput
)
elseif(WIN32) elseif(WIN32)
unset(VULKAN_SDK_DIRS CACHE) unset(VULKAN_SDK_DIRS CACHE)
get_filename_component(VULKAN_SDK_DIRS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\LunarG\\VulkanSDK;VK_SDK_PATHs]" ABSOLUTE CACHE) get_filename_component(VULKAN_SDK_DIRS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\LunarG\\VulkanSDK;VK_SDK_PATHs]" ABSOLUTE CACHE)
if (NOT ${VULKAN_SDK_DIRS} STREQUAL "/registry") if (NOT ${VULKAN_SDK_DIRS} STREQUAL "/registry")
message(STATUS "Enabling Vulkan support") message(STATUS "Enabling Vulkan support")
list(GET VULKAN_SDK_DIRS 0 VULKAN_SDK_DIR) list(GET VULKAN_SDK_DIRS 0 VULKAN_SDK_DIR)
list(APPEND _EXTRA_INCLUDES ${VULKAN_SDK_DIR}/Include) target_include_directories(boo PRIVATE "${VULKAN_SDK_DIR}/Include")
list(APPEND _BOO_SYS_DEFINES -DBOO_HAS_VULKAN=1 -DVK_USE_PLATFORM_WIN32_KHR=1) target_compile_definitions(boo PUBLIC
list(APPEND _BOO_SYS_INCLUDES "${VULKAN_SDK_DIR}/Include") -DBOO_HAS_VULKAN=1
list(APPEND PLAT_SRCS lib/graphicsdev/Vulkan.cpp -DVK_USE_PLATFORM_WIN32_KHR=1
lib/graphicsdev/VulkanDispatchTable.cpp) )
target_sources(boo PRIVATE
lib/graphicsdev/Vulkan.cpp
lib/graphicsdev/VulkanDispatchTable.cpp
)
endif() endif()
find_file(TE_VIRTUAL_MIDI_H teVirtualMIDI.h PATHS find_file(TE_VIRTUAL_MIDI_H teVirtualMIDI.h PATHS
"$ENV{PROGRAMFILES\(X86\)}/Tobias Erichsen/teVirtualMIDISDK/C-Binding") "$ENV{PROGRAMFILES\(X86\)}/Tobias Erichsen/teVirtualMIDISDK/C-Binding")
find_file(TE_VIRTUAL_MIDI_H teVirtualMIDI.h
PATHS
"$ENV{PROGRAMFILES\(X86\)}/Tobias Erichsen/teVirtualMIDISDK/C-Binding"
)
if (NO AND TE_VIRTUAL_MIDI_H) if (NO AND TE_VIRTUAL_MIDI_H)
message(STATUS "Enabling teVirtualMIDI") message(STATUS "Enabling teVirtualMIDI")
get_filename_component(TE_VIRTUAL_MIDI_DIR ${TE_VIRTUAL_MIDI_H} DIRECTORY) get_filename_component(TE_VIRTUAL_MIDI_DIR ${TE_VIRTUAL_MIDI_H} DIRECTORY)
list(APPEND _EXTRA_INCLUDES ${TE_VIRTUAL_MIDI_DIR}) target_include_directories(boo PRIVATE ${TE_VIRTUAL_MIDI_DIR})
add_definitions("-DTE_VIRTUAL_MIDI=1") add_definitions("-DTE_VIRTUAL_MIDI=1")
endif() endif()
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/win/ApplicationWin32.cpp lib/audiodev/AudioMatrixSSE.cpp
lib/win/WindowWin32.cpp lib/audiodev/WASAPI.cpp
lib/win/WinCommon.hpp lib/graphicsdev/D3D11.cpp
lib/win/Win32Common.hpp lib/inputdev/HIDListenerWinUSB.cpp
lib/inputdev/HIDListenerWinUSB.cpp lib/inputdev/HIDDeviceWinUSB.cpp
lib/inputdev/HIDDeviceWinUSB.cpp lib/win/ApplicationWin32.cpp
lib/graphicsdev/D3D11.cpp lib/win/WindowWin32.cpp
lib/audiodev/WASAPI.cpp lib/win/WinCommon.hpp
lib/audiodev/AudioMatrixSSE.cpp) lib/win/Win32Common.hpp
list(APPEND PLAT_HDRS include/boo/graphicsdev/D3D.hpp
include/boo/graphicsdev/D3D.hpp) )
list(APPEND _BOO_SYS_DEFINES -DUNICODE -D_UNICODE) target_compile_definitions(boo PUBLIC
-DUNICODE
list(APPEND _BOO_SYS_LIBS Winusb opengl32 Setupapi Imm32 Winmm Shlwapi Hid Xinput) -D_UNICODE
)
target_link_libraries(boo PUBLIC
Hid
Imm32
Setupapi
Shlwapi
Winmm
Winusb opengl32
Xinput
)
elseif(APPLE) elseif(APPLE)
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/mac/ApplicationCocoa.mm lib/audiodev/AQS.cpp
lib/mac/WindowCocoa.mm lib/audiodev/AudioMatrixSSE.cpp
lib/mac/CocoaCommon.hpp lib/inputdev/HIDListenerIOKit.cpp
lib/inputdev/HIDListenerIOKit.cpp lib/inputdev/HIDDeviceIOKit.cpp
lib/inputdev/HIDDeviceIOKit.cpp lib/mac/ApplicationCocoa.mm
lib/graphicsdev/Metal.mm lib/mac/WindowCocoa.mm
lib/audiodev/AQS.cpp lib/mac/CocoaCommon.hpp
lib/audiodev/AudioMatrixSSE.cpp) lib/graphicsdev/Metal.mm
set_source_files_properties(lib/mac/ApplicationCocoa.mm
lib/mac/WindowCocoa.mm
lib/graphicsdev/Metal.mm
PROPERTIES COMPILE_FLAGS -fobjc-arc)
list(APPEND PLAT_HDRS lib/CFPointer.hpp
lib/CFPointer.hpp lib/inputdev/IOKitPointer.hpp
include/boo/graphicsdev/Metal.hpp include/boo/graphicsdev/Metal.hpp
lib/inputdev/IOKitPointer.hpp) )
set_source_files_properties(
lib/mac/ApplicationCocoa.mm
lib/mac/WindowCocoa.mm
lib/graphicsdev/Metal.mm
PROPERTIES COMPILE_FLAGS -fobjc-arc
)
find_library(APPKIT_LIBRARY AppKit) find_library(APPKIT_LIBRARY AppKit)
find_library(IOKIT_LIBRARY IOKit) find_library(IOKIT_LIBRARY IOKit)
@ -146,7 +238,7 @@ elseif(APPLE)
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER 10.11) if (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER 10.11)
set(BOO_HAS_METAL ON CACHE BOOL "Metal is available in this OS X version" FORCE) set(BOO_HAS_METAL ON CACHE BOOL "Metal is available in this OS X version" FORCE)
find_library(METAL_LIBRARY Metal) find_library(METAL_LIBRARY Metal)
list(APPEND _BOO_SYS_DEFINES -DBOO_HAS_METAL=1) target_compile_definitions(boo PUBLIC -DBOO_HAS_METAL=1)
else() else()
set(METAL_LIBRARY "") set(METAL_LIBRARY "")
endif() endif()
@ -155,31 +247,39 @@ elseif(APPLE)
find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox) find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
find_library(COREAUDIO_LIBRARY CoreAudio) find_library(COREAUDIO_LIBRARY CoreAudio)
find_library(COREMIDI_LIBRARY CoreMIDI) find_library(COREMIDI_LIBRARY CoreMIDI)
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${METAL_LIBRARY}
${QUARTZCORE_LIBRARY} ${COREVIDEO_LIBRARY} ${AUDIOTOOLBOX_LIBRARY}
${COREAUDIO_LIBRARY} ${COREMIDI_LIBRARY})
target_link_libraries(boo PUBLIC
${APPKIT_LIBRARY}
${AUDIOTOOLBOX_LIBRARY}
${COREAUDIO_LIBRARY}
${COREMIDI_LIBRARY}
${COREVIDEO_LIBRARY}
${IOKIT_LIBRARY}
${METAL_LIBRARY}
${QUARTZCORE_LIBRARY}
)
elseif(NX) elseif(NX)
list(APPEND _BOO_SYS_DEFINES -DBOO_HAS_NX=1) target_compile_definitions(boo PUBLIC -DBOO_HAS_NX=1)
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/nx/ApplicationNX.cpp lib/nx/ApplicationNX.cpp
lib/nx/WindowNX.cpp lib/nx/WindowNX.cpp
lib/audiodev/AudioMatrix.cpp lib/audiodev/AudioMatrix.cpp
lib/inputdev/HIDListenerNX.cpp lib/inputdev/HIDListenerNX.cpp
lib/inputdev/HIDDeviceNX.cpp) lib/inputdev/HIDDeviceNX.cpp
list(APPEND _BOO_SYS_LIBS nx_runtime) )
target_link_libraries(boo PUBLIC nx_runtime)
else(NOT GEKKO) else(NOT GEKKO)
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/x11/XlibCommon.hpp lib/audiodev/LinuxMidi.hpp
lib/x11/ApplicationUnix.cpp lib/graphicsdev/GL.cpp
lib/x11/ApplicationXlib.hpp lib/graphicsdev/GLX.cpp
lib/x11/ApplicationWayland.hpp lib/x11/XlibCommon.hpp
lib/x11/WindowXlib.cpp lib/x11/ApplicationUnix.cpp
lib/x11/WindowWayland.cpp lib/x11/ApplicationWayland.hpp
lib/graphicsdev/GL.cpp lib/x11/ApplicationXlib.hpp
lib/graphicsdev/GLX.cpp lib/x11/WindowWayland.cpp
lib/audiodev/LinuxMidi.hpp) lib/x11/WindowXlib.cpp
)
find_package(PkgConfig) find_package(PkgConfig)
if(PKG_CONFIG_FOUND) if(PKG_CONFIG_FOUND)
@ -188,84 +288,120 @@ else(NOT GEKKO)
find_path(DBUS_INCLUDE_DIR find_path(DBUS_INCLUDE_DIR
NAMES NAMES
dbus/dbus.h dbus/dbus.h
HINTS HINTS
${dbus_pkg_INCLUDE_DIRS} ${dbus_pkg_INCLUDE_DIRS}
PATH_SUFFIXES PATH_SUFFIXES
include/ include/
include/dbus-1.0/ include/dbus-1.0/
dbus-1.0/) dbus-1.0/
)
find_path(DBUS_ARCH_INCLUDE_DIR find_path(DBUS_ARCH_INCLUDE_DIR
NAMES NAMES
dbus/dbus-arch-deps.h dbus/dbus-arch-deps.h
HINTS HINTS
${dbus_pkg_INCLUDE_DIRS} ${dbus_pkg_INCLUDE_DIRS}
PATHS PATHS
# TODO use CMAKE_SYSTEM_PROCESSOR or similar? # TODO use CMAKE_SYSTEM_PROCESSOR or similar?
/usr/lib/dbus-1.0/include /usr/lib/dbus-1.0/include
/usr/local/lib/dbus-1.0/include /usr/local/lib/dbus-1.0/include
/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ /usr/lib/x86_64-linux-gnu/dbus-1.0/include/
PATH_SUFFIXES PATH_SUFFIXES
dbus-1.0/include/) dbus-1.0/include/
)
find_library(DBUS_LIBRARY find_library(DBUS_LIBRARY
NAMES NAMES
dbus dbus-1 dbus
dbus-1
HINTS HINTS
${dbus_pkg_LIBRARY_DIRS} ${dbus_pkg_LIBRARY_DIRS}
PATH_SUFFIXES PATH_SUFFIXES
lib lib
lib32 lib32
lib64) lib64
)
find_path(PULSEAUDIO_INCLUDE_DIR find_path(PULSEAUDIO_INCLUDE_DIR
NAMES pulse/pulseaudio.h) NAMES pulse/pulseaudio.h
)
if(PULSEAUDIO_INCLUDE_DIR-NOTFOUND) if(PULSEAUDIO_INCLUDE_DIR-NOTFOUND)
message(FATAL_ERROR "Unix build of boo requires pulseaudio") message(FATAL_ERROR "Unix build of boo requires pulseaudio")
endif() endif()
list(APPEND PLAT_SRCS lib/audiodev/PulseAudio.cpp) target_sources(boo PRIVATE lib/audiodev/PulseAudio.cpp)
list(APPEND _BOO_SYS_LIBS pulse) target_link_libraries(boo PUBLIC pulse)
if(DBUS_INCLUDE_DIR-NOTFOUND) if(DBUS_INCLUDE_DIR-NOTFOUND)
message(FATAL_ERROR "Unix build of boo requires dbus") message(FATAL_ERROR "Unix build of boo requires dbus")
endif() endif()
list(APPEND _EXTRA_INCLUDES ${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) target_include_directories(boo PRIVATE
list(APPEND _BOO_SYS_LIBS X11 Xi Xrandr GL asound ${DBUS_LIBRARY} pthread) ${DBUS_ARCH_INCLUDE_DIR}
${DBUS_INCLUDE_DIR}
)
target_link_libraries(boo
PUBLIC
asound
${DBUS_LIBRARY}
GL
pthread
X11
Xi
Xrandr
)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
find_path(VULKAN_INCLUDE_DIR find_path(VULKAN_INCLUDE_DIR
NAMES vulkan/vulkan.h) NAMES vulkan/vulkan.h
)
if(VULKAN_INCLUDE_DIR) if(VULKAN_INCLUDE_DIR)
message(STATUS "Enabling Vulkan support") message(STATUS "Enabling Vulkan support")
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/graphicsdev/Vulkan.cpp lib/graphicsdev/Vulkan.cpp
lib/graphicsdev/VulkanDispatchTable.cpp) lib/graphicsdev/VulkanDispatchTable.cpp
list(APPEND _BOO_SYS_DEFINES -DBOO_HAS_VULKAN=1 -DVK_USE_PLATFORM_XCB_KHR=1) )
target_compile_definitions(boo
PUBLIC
-DBOO_HAS_VULKAN=1
-DVK_USE_PLATFORM_XCB_KHR=1
)
endif() endif()
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/inputdev/HIDListenerUdev.cpp lib/audiodev/AudioMatrixSSE.cpp
lib/inputdev/HIDDeviceUdev.cpp lib/inputdev/HIDDeviceUdev.cpp
lib/audiodev/AudioMatrixSSE.cpp) lib/inputdev/HIDListenerUdev.cpp
list(APPEND _BOO_SYS_LIBS xcb X11-xcb dl udev) )
target_link_libraries(boo
PUBLIC
dl
xcb
X11-xcb
udev
)
else() else()
list(APPEND PLAT_SRCS target_sources(boo PRIVATE
lib/inputdev/HIDListenerBSD.cpp lib/audiodev/AudioMatrixSSE.cpp
lib/inputdev/HIDDeviceBSD.cpp lib/inputdev/HIDDeviceBSD.cpp
lib/audiodev/AudioMatrixSSE.cpp) lib/inputdev/HIDListenerBSD.cpp
list(APPEND _BOO_SYS_LIBS execinfo) )
target_link_libraries(boo
PUBLIC
execinfo
)
endif() endif()
endif() endif()
if(NOT NX) if(NOT NX)
# For some reason, clang takes forever if glew.c is not built with -Os
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
set_source_files_properties(lib/graphicsdev/glew.c PROPERTIES COMPILE_FLAGS -Os)
endif()
# Empty link args for boo's use # Empty link args for boo's use
function(glslang_set_link_args TARGET) function(glslang_set_link_args TARGET)
endfunction(glslang_set_link_args) endfunction(glslang_set_link_args)
@ -286,67 +422,29 @@ if(NOT NX)
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/glslang PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/glslang
) )
list(APPEND _BOO_SYS_LIBS glslang soxr xxhash OSDependent OGLCompiler SPIRV glslang-default-resource-limits) target_link_libraries(boo
PUBLIC
glslang
glslang-default-resource-limits
OGLCompiler
OSDependent
soxr
SPIRV
xxhash
)
endif() endif()
list(APPEND _EXTRA_INCLUDES glslang soxr/src) target_link_libraries(boo PUBLIC logvisor)
target_include_directories(boo
PUBLIC
include
PRIVATE
glslang
soxr/src
${CMAKE_CURRENT_SOURCE_DIR}
)
add_library(boo
lib/inputdev/DeviceBase.cpp include/boo/inputdev/DeviceBase.hpp
lib/inputdev/CafeProPad.cpp include/boo/inputdev/CafeProPad.hpp
lib/inputdev/RevolutionPad.cpp include/boo/inputdev/RevolutionPad.hpp
lib/inputdev/DolphinSmashAdapter.cpp include/boo/inputdev/DolphinSmashAdapter.hpp
lib/inputdev/NintendoPowerA.cpp include/boo/inputdev/NintendoPowerA.hpp
lib/inputdev/DualshockPad.cpp include/boo/inputdev/DualshockPad.hpp
include/boo/inputdev/XInputPad.hpp
lib/inputdev/GenericPad.cpp include/boo/inputdev/GenericPad.hpp
lib/inputdev/DeviceSignature.cpp include/boo/inputdev/DeviceSignature.hpp
lib/inputdev/DeviceFinder.cpp include/boo/inputdev/DeviceFinder.hpp
lib/inputdev/HIDParser.cpp include/boo/inputdev/HIDParser.hpp
lib/inputdev/IHIDDevice.hpp
lib/audiodev/Common.hpp
lib/audiodev/WAVOut.cpp
lib/audiodev/AudioMatrix.hpp
lib/audiodev/AudioVoiceEngine.hpp
lib/audiodev/AudioVoiceEngine.cpp
lib/audiodev/AudioVoice.hpp
lib/audiodev/AudioVoice.cpp
lib/audiodev/AudioSubmix.hpp
lib/audiodev/AudioSubmix.cpp
lib/audiodev/LtRtProcessing.hpp
lib/audiodev/LtRtProcessing.cpp
lib/audiodev/MIDIEncoder.cpp
lib/audiodev/MIDIDecoder.cpp
lib/audiodev/MIDICommon.hpp
lib/audiodev/MIDICommon.cpp
lib/Common.hpp
include/boo/inputdev/IHIDListener.hpp
include/boo/IGraphicsContext.hpp
include/boo/graphicsdev/IGraphicsDataFactory.hpp
include/boo/graphicsdev/IGraphicsCommandQueue.hpp
lib/graphicsdev/Common.hpp
lib/graphicsdev/Common.cpp
include/boo/audiodev/IAudioSubmix.hpp
include/boo/audiodev/IAudioVoice.hpp
include/boo/audiodev/IMIDIPort.hpp
include/boo/audiodev/IMIDIReader.hpp
include/boo/audiodev/MIDIEncoder.hpp
include/boo/audiodev/MIDIDecoder.hpp
include/boo/audiodev/IAudioVoiceEngine.hpp
include/boo/IWindow.hpp
include/boo/IApplication.hpp
include/boo/ThreadLocalPtr.hpp
include/boo/DeferredWindowEvents.hpp
include/boo/System.hpp
include/boo/BooObject.hpp
include/boo/boo.hpp
InputDeviceClasses.cpp
${PLAT_SRCS}
${PLAT_HDRS})
target_link_libraries(boo PUBLIC ${_BOO_SYS_LIBS} logvisor)
target_compile_definitions(boo PUBLIC ${_BOO_SYS_DEFINES})
target_include_directories(boo PUBLIC include ${_BOO_SYS_INCLUDES}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${_EXTRA_INCLUDES})
if(COMMAND add_sanitizers) if(COMMAND add_sanitizers)
add_sanitizers(boo) add_sanitizers(boo)
endif() endif()

View File

@ -1,8 +1,6 @@
#pragma once #pragma once
#include <atomic> #include <atomic>
#include <mutex>
#include "nxstl/mutex"
namespace boo { namespace boo {
@ -13,11 +11,10 @@ protected:
virtual ~IObj() = default; virtual ~IObj() = default;
public: public:
virtual std::unique_lock<std::recursive_mutex> destructorLock() = 0; void increment() noexcept { m_refCount.fetch_add(1, std::memory_order_relaxed); }
void increment() { m_refCount++; } void decrement() noexcept {
void decrement() { if (m_refCount.fetch_sub(1, std::memory_order_release) == 1) {
if (m_refCount.fetch_sub(1) == 1) { std::atomic_thread_fence(std::memory_order_acquire);
auto lk = destructorLock();
delete this; delete this;
} }
} }
@ -28,17 +25,17 @@ class ObjToken {
SubCls* m_obj = nullptr; SubCls* m_obj = nullptr;
public: public:
ObjToken() = default; ObjToken() noexcept = default;
ObjToken(SubCls* obj) : m_obj(obj) { ObjToken(SubCls* obj) noexcept : m_obj(obj) {
if (m_obj) if (m_obj)
m_obj->increment(); m_obj->increment();
} }
ObjToken(const ObjToken& other) : m_obj(other.m_obj) { ObjToken(const ObjToken& other) noexcept : m_obj(other.m_obj) {
if (m_obj) if (m_obj)
m_obj->increment(); m_obj->increment();
} }
ObjToken(ObjToken&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; } ObjToken(ObjToken&& other) noexcept : m_obj(other.m_obj) { other.m_obj = nullptr; }
ObjToken& operator=(SubCls* obj) { ObjToken& operator=(SubCls* obj) noexcept {
if (m_obj) if (m_obj)
m_obj->decrement(); m_obj->decrement();
m_obj = obj; m_obj = obj;
@ -46,7 +43,7 @@ public:
m_obj->increment(); m_obj->increment();
return *this; return *this;
} }
ObjToken& operator=(const ObjToken& other) { ObjToken& operator=(const ObjToken& other) noexcept {
if (m_obj) if (m_obj)
m_obj->decrement(); m_obj->decrement();
m_obj = other.m_obj; m_obj = other.m_obj;
@ -54,26 +51,28 @@ public:
m_obj->increment(); m_obj->increment();
return *this; return *this;
} }
ObjToken& operator=(ObjToken&& other) { ObjToken& operator=(ObjToken&& other) noexcept {
if (m_obj) if (m_obj)
m_obj->decrement(); m_obj->decrement();
m_obj = other.m_obj; m_obj = other.m_obj;
other.m_obj = nullptr; other.m_obj = nullptr;
return *this; return *this;
} }
~ObjToken() { ~ObjToken() noexcept {
if (m_obj) if (m_obj)
m_obj->decrement(); m_obj->decrement();
} }
SubCls* get() const { return m_obj; } SubCls* get() const noexcept { return m_obj; }
SubCls* operator->() const { return m_obj; } SubCls* operator->() const noexcept { return m_obj; }
SubCls& operator*() const { return *m_obj; } SubCls& operator*() const noexcept { return *m_obj; }
template <class T> template <class T>
T* cast() const { T* cast() const noexcept {
return static_cast<T*>(m_obj); return static_cast<T*>(m_obj);
} }
operator bool() const { return m_obj != nullptr; } explicit operator bool() const noexcept { return m_obj != nullptr; }
void reset() { constexpr bool operator==(const ObjToken& other) const noexcept { return m_obj == other.m_obj; }
constexpr bool operator!=(const ObjToken& other) const noexcept { return !(*this == other); }
void reset() noexcept {
if (m_obj) if (m_obj)
m_obj->decrement(); m_obj->decrement();
m_obj = nullptr; m_obj = nullptr;

View File

@ -1,8 +1,11 @@
#pragma once #pragma once
#include <boo/boo.hpp> #include <chrono>
#include <mutex>
#include <condition_variable> #include <condition_variable>
#include <mutex>
#include <vector>
#include "boo/IWindow.hpp"
#include "nxstl/condition_variable" #include "nxstl/condition_variable"
namespace boo { namespace boo {
@ -15,11 +18,11 @@ struct DeferredWindowEvents : public IWindowCallback {
DeferredWindowEvents(Receiver& rec) : m_rec(rec) {} DeferredWindowEvents(Receiver& rec) : m_rec(rec) {}
bool m_destroyed = false; bool m_destroyed = false;
void destroyed() { m_destroyed = true; } void destroyed() override { m_destroyed = true; }
bool m_hasResize = false; bool m_hasResize = false;
SWindowRect m_latestResize; SWindowRect m_latestResize;
void resized(const SWindowRect& rect, bool sync) { void resized(const SWindowRect& rect, bool sync) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_latestResize = rect; m_latestResize = rect;
m_hasResize = true; m_hasResize = true;
@ -112,7 +115,7 @@ struct DeferredWindowEvents : public IWindowCallback {
}; };
std::vector<Command> m_cmds; std::vector<Command> m_cmds;
void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) { void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseDown); m_cmds.emplace_back(Command::Type::MouseDown);
m_cmds.back().m_coord = coord; m_cmds.back().m_coord = coord;
@ -120,7 +123,7 @@ struct DeferredWindowEvents : public IWindowCallback {
m_cmds.back().m_mods = mods; m_cmds.back().m_mods = mods;
} }
void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) { void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseUp); m_cmds.emplace_back(Command::Type::MouseUp);
m_cmds.back().m_coord = coord; m_cmds.back().m_coord = coord;
@ -128,53 +131,53 @@ struct DeferredWindowEvents : public IWindowCallback {
m_cmds.back().m_mods = mods; m_cmds.back().m_mods = mods;
} }
void mouseMove(const SWindowCoord& coord) { void mouseMove(const SWindowCoord& coord) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseMove); m_cmds.emplace_back(Command::Type::MouseMove);
m_cmds.back().m_coord = coord; m_cmds.back().m_coord = coord;
} }
void mouseEnter(const SWindowCoord& coord) { void mouseEnter(const SWindowCoord& coord) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseEnter); m_cmds.emplace_back(Command::Type::MouseEnter);
m_cmds.back().m_coord = coord; m_cmds.back().m_coord = coord;
} }
void mouseLeave(const SWindowCoord& coord) { void mouseLeave(const SWindowCoord& coord) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseLeave); m_cmds.emplace_back(Command::Type::MouseLeave);
m_cmds.back().m_coord = coord; m_cmds.back().m_coord = coord;
} }
void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) { void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::Scroll); m_cmds.emplace_back(Command::Type::Scroll);
m_cmds.back().m_coord = coord; m_cmds.back().m_coord = coord;
m_cmds.back().m_scroll = scroll; m_cmds.back().m_scroll = scroll;
} }
void touchDown(const STouchCoord& coord, uintptr_t tid) { void touchDown(const STouchCoord& coord, uintptr_t tid) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::TouchDown); m_cmds.emplace_back(Command::Type::TouchDown);
m_cmds.back().m_tCoord = coord; m_cmds.back().m_tCoord = coord;
m_cmds.back().m_tid = tid; m_cmds.back().m_tid = tid;
} }
void touchUp(const STouchCoord& coord, uintptr_t tid) { void touchUp(const STouchCoord& coord, uintptr_t tid) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::TouchUp); m_cmds.emplace_back(Command::Type::TouchUp);
m_cmds.back().m_tCoord = coord; m_cmds.back().m_tCoord = coord;
m_cmds.back().m_tid = tid; m_cmds.back().m_tid = tid;
} }
void touchMove(const STouchCoord& coord, uintptr_t tid) { void touchMove(const STouchCoord& coord, uintptr_t tid) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::TouchMove); m_cmds.emplace_back(Command::Type::TouchMove);
m_cmds.back().m_tCoord = coord; m_cmds.back().m_tCoord = coord;
m_cmds.back().m_tid = tid; m_cmds.back().m_tid = tid;
} }
void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) { void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::CharKeyDown); m_cmds.emplace_back(Command::Type::CharKeyDown);
m_cmds.back().m_charcode = charCode; m_cmds.back().m_charcode = charCode;
@ -182,14 +185,14 @@ struct DeferredWindowEvents : public IWindowCallback {
m_cmds.back().m_isRepeat = isRepeat; m_cmds.back().m_isRepeat = isRepeat;
} }
void charKeyUp(unsigned long charCode, EModifierKey mods) { void charKeyUp(unsigned long charCode, EModifierKey mods) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::CharKeyUp); m_cmds.emplace_back(Command::Type::CharKeyUp);
m_cmds.back().m_charcode = charCode; m_cmds.back().m_charcode = charCode;
m_cmds.back().m_mods = mods; m_cmds.back().m_mods = mods;
} }
void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat) { void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::SpecialKeyDown); m_cmds.emplace_back(Command::Type::SpecialKeyDown);
m_cmds.back().m_special = key; m_cmds.back().m_special = key;
@ -197,27 +200,27 @@ struct DeferredWindowEvents : public IWindowCallback {
m_cmds.back().m_isRepeat = isRepeat; m_cmds.back().m_isRepeat = isRepeat;
} }
void specialKeyUp(ESpecialKey key, EModifierKey mods) { void specialKeyUp(ESpecialKey key, EModifierKey mods) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::SpecialKeyUp); m_cmds.emplace_back(Command::Type::SpecialKeyUp);
m_cmds.back().m_special = key; m_cmds.back().m_special = key;
m_cmds.back().m_mods = mods; m_cmds.back().m_mods = mods;
} }
void modKeyDown(EModifierKey mod, bool isRepeat) { void modKeyDown(EModifierKey mod, bool isRepeat) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::ModKeyDown); m_cmds.emplace_back(Command::Type::ModKeyDown);
m_cmds.back().m_mods = mod; m_cmds.back().m_mods = mod;
m_cmds.back().m_isRepeat = isRepeat; m_cmds.back().m_isRepeat = isRepeat;
} }
void modKeyUp(EModifierKey mod) { void modKeyUp(EModifierKey mod) override {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::ModKeyUp); m_cmds.emplace_back(Command::Type::ModKeyUp);
m_cmds.back().m_mods = mod; m_cmds.back().m_mods = mod;
} }
ITextInputCallback* getTextInputCallback() { return m_rec.getTextInputCallback(); } ITextInputCallback* getTextInputCallback() override { return m_rec.getTextInputCallback(); }
void dispatchEvents() { void dispatchEvents() {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);

View File

@ -1,11 +1,12 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <string> #include <string_view>
#include <vector> #include <vector>
#include "IWindow.hpp" #include "boo/IWindow.hpp"
#include "inputdev/DeviceFinder.hpp" #include "boo/System.hpp"
#include "boo/inputdev/DeviceFinder.hpp"
namespace boo { namespace boo {
class IApplication; class IApplication;

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <memory>
#include <cstdint> #include <cstdint>
#include <memory>
namespace boo { namespace boo {
struct IGraphicsCommandQueue; struct IGraphicsCommandQueue;
@ -14,7 +14,7 @@ class IGraphicsContext {
public: public:
enum class EGraphicsAPI { enum class EGraphicsAPI {
None = 0, Invalid = 0,
OpenGL3_3 = 1, OpenGL3_3 = 1,
OpenGL4_2 = 2, OpenGL4_2 = 2,
Vulkan = 3, Vulkan = 3,
@ -26,7 +26,7 @@ public:
}; };
enum class EPixelFormat { enum class EPixelFormat {
None = 0, Invalid = 0,
RGBA8 = 1, /* Default */ RGBA8 = 1, /* Default */
RGBA16 = 2, RGBA16 = 2,
RGBA8_Z24 = 3, RGBA8_Z24 = 3,

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "System.hpp"
#include <memory>
#include <algorithm> #include <algorithm>
#include <memory>
#include <cstring> #include <cstring>
#include "boo/System.hpp"
#undef min #undef min
#undef max #undef max

View File

@ -37,12 +37,12 @@ static inline ComPtr<T>* ReferenceComPtr(ComPtr<T>& ptr) {
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return type(static_cast<T>(a) & static_cast<T>(b)); \ return type(static_cast<T>(a) & static_cast<T>(b)); \
} \ } \
inline type& operator|=(type& a, const type& b) { \ constexpr type& operator|=(type& a, type b) { \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) | static_cast<T>(b)); \ a = type(static_cast<T>(a) | static_cast<T>(b)); \
return a; \ return a; \
} \ } \
inline type& operator&=(type& a, const type& b) { \ constexpr type& operator&=(type& a, type b) { \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) & static_cast<T>(b)); \ a = type(static_cast<T>(a) & static_cast<T>(b)); \
return a; \ return a; \

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "IApplication.hpp" #include "boo/IApplication.hpp"
namespace boo { namespace boo {

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <array>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
@ -24,7 +25,7 @@ enum class AudioChannel {
struct ChannelMap { struct ChannelMap {
unsigned m_channelCount = 0; unsigned m_channelCount = 0;
AudioChannel m_channels[8] = {}; std::array<AudioChannel, 8> m_channels{};
}; };
static inline unsigned ChannelCount(AudioChannelSet layout) { static inline unsigned ChannelCount(AudioChannelSet layout) {

View File

@ -1,12 +1,16 @@
#pragma once #pragma once
#include "IAudioVoice.hpp" #include <cstddef>
#include "IAudioSubmix.hpp"
#include "IMIDIPort.hpp"
#include "boo/BooObject.hpp"
#include <memory> #include <memory>
#include <string>
#include <utility>
#include <vector> #include <vector>
#include "boo/BooObject.hpp"
#include "boo/audiodev/IAudioSubmix.hpp"
#include "boo/audiodev/IAudioVoice.hpp"
#include "boo/audiodev/IMIDIPort.hpp"
namespace boo { namespace boo {
struct IAudioVoiceEngine; struct IAudioVoiceEngine;

View File

@ -1,9 +1,10 @@
#pragma once #pragma once
#include <string> #include <cstddef>
#include <functional>
#include <vector>
#include <cstdint> #include <cstdint>
#include <functional>
#include <string>
#include <vector>
namespace boo { namespace boo {
struct IAudioVoiceEngine; struct IAudioVoiceEngine;
@ -35,7 +36,7 @@ protected:
: IMIDIPort(parent, virt), IMIDIReceiver(std::move(receiver)) {} : IMIDIPort(parent, virt), IMIDIReceiver(std::move(receiver)) {}
public: public:
virtual ~IMIDIIn(); ~IMIDIIn() override;
}; };
class IMIDIOut : public IMIDIPort { class IMIDIOut : public IMIDIPort {
@ -43,7 +44,7 @@ protected:
IMIDIOut(IAudioVoiceEngine* parent, bool virt) : IMIDIPort(parent, virt) {} IMIDIOut(IAudioVoiceEngine* parent, bool virt) : IMIDIPort(parent, virt) {}
public: public:
virtual ~IMIDIOut(); ~IMIDIOut() override;
virtual size_t send(const void* buf, size_t len) const = 0; virtual size_t send(const void* buf, size_t len) const = 0;
}; };
@ -53,7 +54,7 @@ protected:
: IMIDIPort(parent, virt), IMIDIReceiver(std::move(receiver)) {} : IMIDIPort(parent, virt), IMIDIReceiver(std::move(receiver)) {}
public: public:
virtual ~IMIDIInOut(); ~IMIDIInOut() override;
virtual size_t send(const void* buf, size_t len) const = 0; virtual size_t send(const void* buf, size_t len) const = 0;
}; };

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <cstdlib> #include <cstddef>
#include <cstdint> #include <cstdint>
namespace boo { namespace boo {

View File

@ -1,17 +1,14 @@
#pragma once #pragma once
#include "boo/audiodev/IMIDIReader.hpp" #include <cstdint>
#include "boo/audiodev/IMIDIPort.hpp"
#include <functional>
#include <vector> #include <vector>
namespace boo { namespace boo {
class IMIDIReader;
class MIDIDecoder { class MIDIDecoder {
IMIDIReader& m_out; IMIDIReader& m_out;
uint8_t m_status = 0; uint8_t m_status = 0;
bool _readContinuedValue(std::vector<uint8_t>::const_iterator& it, std::vector<uint8_t>::const_iterator end,
uint32_t& valOut);
public: public:
MIDIDecoder(IMIDIReader& out) : m_out(out) {} MIDIDecoder(IMIDIReader& out) : m_out(out) {}

View File

@ -1,7 +1,9 @@
#pragma once #pragma once
#include <cstdint>
#include <iterator>
#include "boo/audiodev/IMIDIReader.hpp" #include "boo/audiodev/IMIDIReader.hpp"
#include "boo/audiodev/IMIDIPort.hpp"
namespace boo { namespace boo {
@ -9,38 +11,45 @@ template <class Sender>
class MIDIEncoder : public IMIDIReader { class MIDIEncoder : public IMIDIReader {
Sender& m_sender; Sender& m_sender;
uint8_t m_status = 0; uint8_t m_status = 0;
void _sendMessage(const uint8_t* data, size_t len); void _sendMessage(const uint8_t* data, size_t len);
template <typename ContiguousContainer>
void _sendMessage(const ContiguousContainer& container) {
_sendMessage(std::data(container), std::size(container));
}
void _sendContinuedValue(uint32_t val); void _sendContinuedValue(uint32_t val);
public: public:
MIDIEncoder(Sender& sender) : m_sender(sender) {} MIDIEncoder(Sender& sender) : m_sender(sender) {}
void noteOff(uint8_t chan, uint8_t key, uint8_t velocity); void noteOff(uint8_t chan, uint8_t key, uint8_t velocity) override;
void noteOn(uint8_t chan, uint8_t key, uint8_t velocity); void noteOn(uint8_t chan, uint8_t key, uint8_t velocity) override;
void notePressure(uint8_t chan, uint8_t key, uint8_t pressure); void notePressure(uint8_t chan, uint8_t key, uint8_t pressure) override;
void controlChange(uint8_t chan, uint8_t control, uint8_t value); void controlChange(uint8_t chan, uint8_t control, uint8_t value) override;
void programChange(uint8_t chan, uint8_t program); void programChange(uint8_t chan, uint8_t program) override;
void channelPressure(uint8_t chan, uint8_t pressure); void channelPressure(uint8_t chan, uint8_t pressure) override;
void pitchBend(uint8_t chan, int16_t pitch); void pitchBend(uint8_t chan, int16_t pitch) override;
void allSoundOff(uint8_t chan); void allSoundOff(uint8_t chan) override;
void resetAllControllers(uint8_t chan); void resetAllControllers(uint8_t chan) override;
void localControl(uint8_t chan, bool on); void localControl(uint8_t chan, bool on) override;
void allNotesOff(uint8_t chan); void allNotesOff(uint8_t chan) override;
void omniMode(uint8_t chan, bool on); void omniMode(uint8_t chan, bool on) override;
void polyMode(uint8_t chan, bool on); void polyMode(uint8_t chan, bool on) override;
void sysex(const void* data, size_t len); void sysex(const void* data, size_t len) override;
void timeCodeQuarterFrame(uint8_t message, uint8_t value); void timeCodeQuarterFrame(uint8_t message, uint8_t value) override;
void songPositionPointer(uint16_t pointer); void songPositionPointer(uint16_t pointer) override;
void songSelect(uint8_t song); void songSelect(uint8_t song) override;
void tuneRequest(); void tuneRequest() override;
void startSeq(); void startSeq() override;
void continueSeq(); void continueSeq() override;
void stopSeq(); void stopSeq() override;
void reset(); void reset() override;
}; };
} // namespace boo } // namespace boo

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "DeferredWindowEvents.hpp"
#include "IApplication.hpp" #include "IApplication.hpp"
#include "IWindow.hpp" #include "IWindow.hpp"
#include "inputdev/DeviceFinder.hpp" #include "inputdev/DeviceFinder.hpp"
@ -9,4 +10,3 @@
#include "inputdev/NintendoPowerA.hpp" #include "inputdev/NintendoPowerA.hpp"
#include "graphicsdev/IGraphicsCommandQueue.hpp" #include "graphicsdev/IGraphicsCommandQueue.hpp"
#include "graphicsdev/IGraphicsDataFactory.hpp" #include "graphicsdev/IGraphicsDataFactory.hpp"
#include "DeferredWindowEvents.hpp"

View File

@ -2,14 +2,14 @@
#if _WIN32 #if _WIN32
#include "IGraphicsDataFactory.hpp" #include <cstddef>
#include "IGraphicsCommandQueue.hpp"
#include "boo/IGraphicsContext.hpp"
#include "boo/System.hpp"
#include <vector> #include <vector>
#include <unordered_set>
typedef HRESULT(WINAPI* pD3DCreateBlob)(SIZE_T Size, ID3DBlob** ppBlob); #include "boo/BooObject.hpp"
#include "boo/System.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
using pD3DCreateBlob = HRESULT(WINAPI*)(SIZE_T Size, ID3DBlob** ppBlob);
extern pD3DCreateBlob D3DCreateBlobPROC; extern pD3DCreateBlob D3DCreateBlobPROC;
namespace boo { namespace boo {
@ -17,10 +17,10 @@ struct BaseGraphicsData;
class D3D11DataFactory : public IGraphicsDataFactory { class D3D11DataFactory : public IGraphicsDataFactory {
public: public:
virtual ~D3D11DataFactory() = default; ~D3D11DataFactory() override = default;
Platform platform() const { return Platform::D3D11; } Platform platform() const override { return Platform::D3D11; }
const SystemChar* platformName() const { return _SYS_STR("D3D11"); } const SystemChar* platformName() const override { return _SYS_STR("D3D11"); }
class Context final : public IGraphicsDataFactory::Context { class Context final : public IGraphicsDataFactory::Context {
friend class D3D11DataFactoryImpl; friend class D3D11DataFactoryImpl;
@ -30,28 +30,30 @@ public:
~Context(); ~Context();
public: public:
Platform platform() const { return Platform::D3D11; } Platform platform() const override { return Platform::D3D11; }
const SystemChar* platformName() const { return _SYS_STR("D3D11"); } const SystemChar* platformName() const override { return _SYS_STR("D3D11"); }
ObjToken<IGraphicsBufferS> newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); ObjToken<IGraphicsBufferS> newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) override;
ObjToken<IGraphicsBufferD> newDynamicBuffer(BufferUse use, size_t stride, size_t count); ObjToken<IGraphicsBufferD> newDynamicBuffer(BufferUse use, size_t stride, size_t count) override;
ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz); TextureClampMode clampMode, const void* data, size_t sz) override;
ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data, TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz); size_t sz) override;
ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode) override;
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, size_t colorBindCount, ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, size_t colorBindCount,
size_t depthBindCount); size_t depthBindCount) override;
ObjToken<ITextureCubeR> newCubeRenderTexture(size_t width, size_t mips); ObjToken<ITextureCubeR> newCubeRenderTexture(size_t width, size_t mips) override;
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage); ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage) override;
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment, ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control, ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt, ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo, bool asynchronous = true); const AdditionalPipelineInfo& additionalInfo,
bool asynchronous = true) override;
ObjToken<IShaderDataBinding> ObjToken<IShaderDataBinding>
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline, const ObjToken<IGraphicsBuffer>& vbo, newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline, const ObjToken<IGraphicsBuffer>& vbo,
@ -59,7 +61,7 @@ public:
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount,
const ObjToken<ITexture>* texs, const int* bindIdxs, const bool* bindDepth, const ObjToken<ITexture>* texs, const int* bindIdxs, const bool* bindDepth,
size_t baseVert = 0, size_t baseInst = 0); size_t baseVert = 0, size_t baseInst = 0) override;
}; };
static std::vector<uint8_t> CompileHLSL(const char* source, PipelineStage stage); static std::vector<uint8_t> CompileHLSL(const char* source, PipelineStage stage);

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#if BOO_HAS_GL #if BOO_HAS_GL
#include "IGraphicsDataFactory.hpp" #include <cstdint>
#include "IGraphicsCommandQueue.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/BooObject.hpp"
#include "GLSLMacros.hpp" #include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace boo { namespace boo {
struct BaseGraphicsData; struct BaseGraphicsData;
@ -25,35 +26,38 @@ public:
~Context(); ~Context();
public: public:
Platform platform() const { return Platform::OpenGL; } Platform platform() const override { return Platform::OpenGL; }
const SystemChar* platformName() const { return _SYS_STR("OpenGL"); } const SystemChar* platformName() const override { return _SYS_STR("OpenGL"); }
ObjToken<IGraphicsBufferS> newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); ObjToken<IGraphicsBufferS> newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) override;
ObjToken<IGraphicsBufferD> newDynamicBuffer(BufferUse use, size_t stride, size_t count); ObjToken<IGraphicsBufferD> newDynamicBuffer(BufferUse use, size_t stride, size_t count) override;
ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz); TextureClampMode clampMode, const void* data, size_t sz) override;
ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data, TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz); size_t sz) override;
ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode) override;
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindingCount, size_t depthBindingCount); size_t colorBindingCount, size_t depthBindingCount) override;
ObjToken<ITextureCubeR> newCubeRenderTexture(size_t width, size_t mips); ObjToken<ITextureCubeR> newCubeRenderTexture(size_t width, size_t mips) override;
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage); ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage) override;
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment, ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control, ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt, ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo, bool asynchronous = true); const AdditionalPipelineInfo& additionalInfo,
bool asynchronous = true) override;
ObjToken<IShaderDataBinding> newShaderDataBinding( ObjToken<IShaderDataBinding>
const ObjToken<IShaderPipeline>& pipeline, const ObjToken<IGraphicsBuffer>& vbo, newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline, const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo, const ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount, const ObjToken<IGraphicsBuffer>& instVbo, const ObjToken<IGraphicsBuffer>& ibo,
const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufSizes, size_t texCount, const ObjToken<ITexture>* texs, const int* texBindIdx, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount,
const bool* depthBind, size_t baseVert = 0, size_t baseInst = 0); const ObjToken<ITexture>* texs, const int* texBindIdx, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0) override;
}; };
}; };

View File

@ -1,9 +1,12 @@
#pragma once #pragma once
#include "IGraphicsDataFactory.hpp"
#include "boo/IWindow.hpp"
#include <functional>
#include <array> #include <array>
#include <cstddef>
#include <functional>
#include "boo/BooObject.hpp"
#include "boo/IWindow.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace boo { namespace boo {

View File

@ -1,12 +1,13 @@
#pragma once #pragma once
#include <memory> #include <cstddef>
#include <functional>
#include <cstdint> #include <cstdint>
#include <functional>
#include <initializer_list>
#include <vector> #include <vector>
#include "boo/System.hpp"
#include "boo/ThreadLocalPtr.hpp"
#include "boo/BooObject.hpp" #include "boo/BooObject.hpp"
#include "boo/System.hpp"
#ifdef __SWITCH__ #ifdef __SWITCH__
#include <ctype.h> #include <ctype.h>
@ -118,7 +119,7 @@ ENABLE_BITWISE_ENUM(VertexSemantic)
/** Used to create IVertexFormat */ /** Used to create IVertexFormat */
struct VertexElementDescriptor { struct VertexElementDescriptor {
VertexSemantic semantic; VertexSemantic semantic{};
int semanticIdx = 0; int semanticIdx = 0;
VertexElementDescriptor() = default; VertexElementDescriptor() = default;
VertexElementDescriptor(VertexSemantic s, int idx = 0) : semantic(s), semanticIdx(idx) {} VertexElementDescriptor(VertexSemantic s, int idx = 0) : semantic(s), semanticIdx(idx) {}
@ -250,7 +251,8 @@ struct IGraphicsDataFactory {
const VertexFormatInfo& vtxFmt, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo, const AdditionalPipelineInfo& additionalInfo,
bool asynchronous = true) { bool asynchronous = true) {
return newShaderPipeline(vertex, fragment, {}, {}, {}, vtxFmt, additionalInfo, asynchronous); return newShaderPipeline(std::move(vertex), std::move(fragment), {}, {}, {}, vtxFmt, additionalInfo,
asynchronous);
} }
virtual ObjToken<IShaderDataBinding> newShaderDataBinding( virtual ObjToken<IShaderDataBinding> newShaderDataBinding(

View File

@ -2,9 +2,11 @@
#ifdef __APPLE__ #ifdef __APPLE__
#if BOO_HAS_METAL #if BOO_HAS_METAL
#include "IGraphicsDataFactory.hpp" #include "boo/BooObject.hpp"
#include "IGraphicsCommandQueue.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include "boo/System.hpp"
#include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace boo { namespace boo {
struct BaseGraphicsData; struct BaseGraphicsData;

View File

@ -1,9 +1,12 @@
#pragma once #pragma once
#if BOO_HAS_NX #if BOO_HAS_NX
#include "IGraphicsDataFactory.hpp" #include <unordered_map>
#include "IGraphicsCommandQueue.hpp"
#include "nx_compiler.hpp" #include "boo/BooObject.hpp"
#include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "boo/graphicsdev/nx_compiler.hpp"
#include <switch/nvidia/fence.h> #include <switch/nvidia/fence.h>

View File

@ -1,15 +1,16 @@
#pragma once #pragma once
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
#include "IGraphicsDataFactory.hpp"
#include "IGraphicsCommandQueue.hpp"
#include "boo/IGraphicsContext.hpp"
#include "GLSLMacros.hpp"
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <mutex> #include <mutex>
#include <queue> #include <queue>
#include <unordered_map>
#include <vector>
#include "boo/BooObject.hpp"
#include "boo/IGraphicsContext.hpp"
#include "boo/IWindow.hpp"
#include "boo/System.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "boo/graphicsdev/VulkanDispatchTable.hpp" #include "boo/graphicsdev/VulkanDispatchTable.hpp"
/* Forward-declare handle type for Vulkan Memory Allocator */ /* Forward-declare handle type for Vulkan Memory Allocator */

View File

@ -1,11 +1,12 @@
#pragma once #pragma once
#include <cstdint> #include <cstddef>
#include <cstdlib>
#include <cstdio> #include <cstdio>
#include <cstdint>
#include <memory> #include <memory>
#include <vector>
#include <mutex> #include <mutex>
#include <vector>
#include "nxstl/mutex" #include "nxstl/mutex"
#include "boo/System.hpp" #include "boo/System.hpp"
@ -54,18 +55,18 @@ public:
bool sendUSBInterruptTransfer(const uint8_t* data, size_t length); bool sendUSBInterruptTransfer(const uint8_t* data, size_t length);
size_t receiveUSBInterruptTransfer(uint8_t* data, size_t length); size_t receiveUSBInterruptTransfer(uint8_t* data, size_t length);
inline unsigned getVendorId(); inline unsigned getVendorId() const;
inline unsigned getProductId(); inline unsigned getProductId() const;
inline std::string_view getVendorName(); inline std::string_view getVendorName() const;
inline std::string_view getProductName(); inline std::string_view getProductName() const;
/* High-Level API */ /* High-Level API */
#if _WIN32 #if _WIN32
#if !WINDOWS_STORE #if !WINDOWS_STORE
const PHIDP_PREPARSED_DATA getReportDescriptor(); PHIDP_PREPARSED_DATA getReportDescriptor() const;
#endif #endif
#else #else
std::vector<uint8_t> getReportDescriptor(); std::vector<uint8_t> getReportDescriptor() const;
#endif #endif
bool sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message = 0); bool sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message = 0);
size_t receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, size_t receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp,

View File

@ -1,13 +1,13 @@
#pragma once #pragma once
#include <unordered_set> #include <memory>
#include <typeindex>
#include <mutex> #include <mutex>
#include "DeviceToken.hpp" #include <string>
#include "IHIDListener.hpp" #include <unordered_set>
#include "DeviceSignature.hpp"
#include <cstring> #include "boo/inputdev/DeviceSignature.hpp"
#include <cstdio> #include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/IHIDListener.hpp"
#ifdef _WIN32 #ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
@ -41,34 +41,11 @@ private:
/* Friend methods for platform-listener to find/insert/remove /* Friend methods for platform-listener to find/insert/remove
* tokens with type-filtering */ * tokens with type-filtering */
bool _hasToken(const std::string& path) { bool _hasToken(const std::string& path) const {
auto preCheck = m_tokens.find(path); return m_tokens.find(path) != m_tokens.end();
if (preCheck != m_tokens.end())
return true;
return false;
}
bool _insertToken(std::unique_ptr<DeviceToken>&& token) {
if (DeviceSignature::DeviceMatchToken(*token, m_types)) {
m_tokensLock.lock();
TInsertedDeviceToken inseredTok = m_tokens.insert(std::make_pair(token->getDevicePath(), std::move(token)));
m_tokensLock.unlock();
deviceConnected(*inseredTok.first->second);
return true;
}
return false;
}
void _removeToken(const std::string& path) {
auto preCheck = m_tokens.find(path);
if (preCheck != m_tokens.end()) {
DeviceToken& tok = *preCheck->second;
std::shared_ptr<DeviceBase> dev = tok.m_connectedDev;
tok._deviceClose();
deviceDisconnected(tok, dev.get());
m_tokensLock.lock();
m_tokens.erase(preCheck);
m_tokensLock.unlock();
}
} }
bool _insertToken(std::unique_ptr<DeviceToken>&& token);
void _removeToken(const std::string& path);
public: public:
class CDeviceTokensHandle { class CDeviceTokensHandle {
@ -77,31 +54,17 @@ public:
public: public:
CDeviceTokensHandle(DeviceFinder& finder) : m_finder(finder) { m_finder.m_tokensLock.lock(); } CDeviceTokensHandle(DeviceFinder& finder) : m_finder(finder) { m_finder.m_tokensLock.lock(); }
~CDeviceTokensHandle() { m_finder.m_tokensLock.unlock(); } ~CDeviceTokensHandle() { m_finder.m_tokensLock.unlock(); }
TDeviceTokens::iterator begin() { return m_finder.m_tokens.begin(); }
TDeviceTokens::iterator end() { return m_finder.m_tokens.end(); } TDeviceTokens::iterator begin() noexcept { return m_finder.m_tokens.begin(); }
TDeviceTokens::iterator end() noexcept { return m_finder.m_tokens.end(); }
TDeviceTokens::const_iterator begin() const noexcept { return m_finder.m_tokens.begin(); }
TDeviceTokens::const_iterator end() const noexcept { return m_finder.m_tokens.end(); }
}; };
/* Application must specify its interested device-types */ /* Application must specify its interested device-types */
DeviceFinder(std::unordered_set<uint64_t> types) { DeviceFinder(std::unordered_set<uint64_t> types);
if (skDevFinder) { virtual ~DeviceFinder();
fmt::print(stderr, fmt("only one instance of CDeviceFinder may be constructed"));
abort();
}
skDevFinder = this;
for (const uint64_t& typeHash : types) {
const DeviceSignature* sigIter = BOO_DEVICE_SIGS;
while (sigIter->m_name) {
if (sigIter->m_typeHash == typeHash)
m_types.push_back(sigIter);
++sigIter;
}
}
}
virtual ~DeviceFinder() {
if (m_listener)
m_listener->stopScanning();
skDevFinder = NULL;
}
/* Get interested device-type mask */ /* Get interested device-type mask */
const DeviceSignature::TDeviceSignatureSet& getTypes() const { return m_types; } const DeviceSignature::TDeviceSignatureSet& getTypes() const { return m_types; }
@ -110,29 +73,11 @@ public:
CDeviceTokensHandle getTokens() { return CDeviceTokensHandle(*this); } CDeviceTokensHandle getTokens() { return CDeviceTokensHandle(*this); }
/* Automatic device scanning */ /* Automatic device scanning */
bool startScanning() { bool startScanning();
if (!m_listener) bool stopScanning();
m_listener = IHIDListenerNew(*this);
if (m_listener)
return m_listener->startScanning();
return false;
}
bool stopScanning() {
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
return m_listener->stopScanning();
return false;
}
/* Manual device scanning */ /* Manual device scanning */
bool scanNow() { bool scanNow();
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
return m_listener->scanNow();
return false;
}
virtual void deviceConnected(DeviceToken&) {} virtual void deviceConnected(DeviceToken&) {}
virtual void deviceDisconnected(DeviceToken&, DeviceBase*) {} virtual void deviceDisconnected(DeviceToken&, DeviceBase*) {}

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include <vector> #include <cstdint>
#include <functional> #include <functional>
#include <typeindex>
#include <memory> #include <memory>
#include <string> #include <string>
#include <typeindex>
#include <vector>
namespace boo { namespace boo {
@ -16,14 +17,16 @@ class DeviceBase;
#define dev_typeid(type) std::hash<std::string>()(#type) #define dev_typeid(type) std::hash<std::string>()(#type)
struct DeviceSignature { struct DeviceSignature {
typedef std::vector<const DeviceSignature*> TDeviceSignatureSet; using TDeviceSignatureSet = std::vector<const DeviceSignature*>;
typedef std::function<std::shared_ptr<DeviceBase>(DeviceToken*)> TFactoryLambda; using TFactoryLambda = std::function<std::shared_ptr<DeviceBase>(DeviceToken*)>;
const char* m_name;
uint64_t m_typeHash; const char* m_name = nullptr;
unsigned m_vid, m_pid; uint64_t m_typeHash = 0;
unsigned m_vid = 0;
unsigned m_pid = 0;
TFactoryLambda m_factory; TFactoryLambda m_factory;
DeviceType m_type; DeviceType m_type{};
DeviceSignature() : m_name(NULL), m_typeHash(dev_typeid(DeviceSignature)) {} /* Sentinel constructor */ DeviceSignature() : m_typeHash(dev_typeid(DeviceSignature)) {} /* Sentinel constructor */
DeviceSignature(const char* name, uint64_t typeHash, unsigned vid, unsigned pid, TFactoryLambda&& factory, DeviceSignature(const char* name, uint64_t typeHash, unsigned vid, unsigned pid, TFactoryLambda&& factory,
DeviceType type = DeviceType::None) DeviceType type = DeviceType::None)
: m_name(name), m_typeHash(typeHash), m_vid(vid), m_pid(pid), m_factory(factory), m_type(type) {} : m_name(name), m_typeHash(typeHash), m_vid(vid), m_pid(pid), m_factory(factory), m_type(type) {}

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
#include <memory>
#include <string> #include <string>
#include "DeviceBase.hpp"
#include "DeviceSignature.hpp" #include "boo/inputdev/DeviceBase.hpp"
#include "boo/inputdev/DeviceSignature.hpp"
namespace boo { namespace boo {
@ -28,14 +30,7 @@ class DeviceToken {
public: public:
DeviceToken(const DeviceToken&) = delete; DeviceToken(const DeviceToken&) = delete;
DeviceToken(const DeviceToken&& other) DeviceToken(DeviceToken&& other) noexcept = default;
: m_devType(other.m_devType)
, m_vendorId(other.m_vendorId)
, m_productId(other.m_productId)
, m_vendorName(other.m_vendorName)
, m_productName(other.m_productName)
, m_devPath(other.m_devPath)
, m_connectedDev(other.m_connectedDev) {}
DeviceToken(DeviceType devType, unsigned vid, unsigned pid, const char* vname, const char* pname, const char* path) DeviceToken(DeviceType devType, unsigned vid, unsigned pid, const char* vname, const char* pname, const char* path)
: m_devType(devType), m_vendorId(vid), m_productId(pid), m_devPath(path), m_connectedDev(NULL) { : m_devType(devType), m_vendorId(vid), m_productId(pid), m_devPath(path), m_connectedDev(NULL) {
if (vname) if (vname)
@ -44,6 +39,12 @@ public:
m_productName = pname; m_productName = pname;
} }
DeviceToken& operator=(const DeviceToken&) = delete;
DeviceToken& operator=(DeviceToken&&) noexcept = default;
bool operator==(const DeviceToken& rhs) const { return m_devPath == rhs.m_devPath; }
bool operator<(const DeviceToken& rhs) const { return m_devPath < rhs.m_devPath; }
DeviceType getDeviceType() const { return m_devType; } DeviceType getDeviceType() const { return m_devType; }
unsigned getVendorId() const { return m_vendorId; } unsigned getVendorId() const { return m_vendorId; }
unsigned getProductId() const { return m_productId; } unsigned getProductId() const { return m_productId; }
@ -56,9 +57,6 @@ public:
m_connectedDev = DeviceSignature::DeviceNew(*this); m_connectedDev = DeviceSignature::DeviceNew(*this);
return m_connectedDev; return m_connectedDev;
} }
bool operator==(const DeviceToken& rhs) const { return m_devPath == rhs.m_devPath; }
bool operator<(const DeviceToken& rhs) const { return m_devPath < rhs.m_devPath; }
}; };
} // namespace boo } // namespace boo

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include "DeviceBase.hpp"
#include "../System.hpp" #include "boo/System.hpp"
#include "boo/inputdev/DeviceBase.hpp"
namespace boo { namespace boo {
@ -67,14 +68,14 @@ class DolphinSmashAdapter final : public TDeviceBase<IDolphinSmashAdapterCallbac
uint8_t m_rumbleRequest = 0; uint8_t m_rumbleRequest = 0;
bool m_hardStop[4] = {false}; bool m_hardStop[4] = {false};
uint8_t m_rumbleState = 0xf; /* Force initial send of stop-rumble command */ uint8_t m_rumbleState = 0xf; /* Force initial send of stop-rumble command */
void deviceDisconnected(); void deviceDisconnected() override;
void initialCycle(); void initialCycle() override;
void transferCycle(); void transferCycle() override;
void finalCycle(); void finalCycle() override;
public: public:
DolphinSmashAdapter(DeviceToken* token); DolphinSmashAdapter(DeviceToken* token);
~DolphinSmashAdapter(); ~DolphinSmashAdapter() override;
void setCallback(IDolphinSmashAdapterCallback* cb) { void setCallback(IDolphinSmashAdapterCallback* cb) {
TDeviceBase<IDolphinSmashAdapterCallback>::setCallback(cb); TDeviceBase<IDolphinSmashAdapterCallback>::setCallback(cb);

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <type_traits>
#include "DeviceBase.hpp"
#include "boo/System.hpp" #include "boo/System.hpp"
#include "boo/inputdev/DeviceBase.hpp"
namespace boo { namespace boo {
@ -112,15 +113,15 @@ class DualshockPad final : public TDeviceBase<IDualshockPadCallback> {
uint8_t m_rumbleIntensity[2]; uint8_t m_rumbleIntensity[2];
EDualshockLED m_led; EDualshockLED m_led;
DualshockOutReport m_report; DualshockOutReport m_report;
void deviceDisconnected(); void deviceDisconnected() override;
void initialCycle(); void initialCycle() override;
void transferCycle(); void transferCycle() override;
void finalCycle(); void finalCycle() override;
void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message); void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override;
public: public:
DualshockPad(DeviceToken* token); DualshockPad(DeviceToken* token);
~DualshockPad(); ~DualshockPad() override;
void startRumble(EDualshockMotor motor, uint8_t duration = 254, uint8_t intensity = 255) { void startRumble(EDualshockMotor motor, uint8_t duration = 254, uint8_t intensity = 255) {
m_rumbleRequest |= motor; m_rumbleRequest |= motor;
@ -136,7 +137,7 @@ public:
void stopRumble(int motor) { m_rumbleRequest &= ~EDualshockMotor(motor); } void stopRumble(int motor) { m_rumbleRequest &= ~EDualshockMotor(motor); }
EDualshockLED getLED() { return m_led; } EDualshockLED getLED() const { return m_led; }
void setLED(EDualshockLED led, bool on = true) { void setLED(EDualshockLED led, bool on = true) {
if (on) if (on)

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include "DeviceBase.hpp" #include <functional>
#include "HIDParser.hpp"
#include <map> #include "boo/inputdev/DeviceBase.hpp"
#include <mutex> #include "boo/inputdev/HIDParser.hpp"
namespace boo { namespace boo {
@ -18,11 +18,11 @@ class GenericPad final : public TDeviceBase<IGenericPadCallback> {
public: public:
GenericPad(DeviceToken* token); GenericPad(DeviceToken* token);
~GenericPad(); ~GenericPad() override;
void deviceDisconnected(); void deviceDisconnected() override;
void initialCycle(); void initialCycle() override;
void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message); void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override;
void enumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const; void enumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const;
}; };

View File

@ -1,10 +1,14 @@
#pragma once #pragma once
#include "boo/System.hpp" #include <cstddef>
#include <vector> #include <cstdint>
#include <stack>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <stack>
#include <utility>
#include <vector>
#include "boo/System.hpp"
#if _WIN32 #if _WIN32
#include <hidsdi.h> #include <hidsdi.h>

View File

@ -1,15 +1,18 @@
#pragma once #pragma once
#include <unordered_map> #include <memory>
#include <mutex> #include <mutex>
#include "DeviceToken.hpp" #include <unordered_map>
#include <utility>
#include "boo/inputdev/DeviceToken.hpp"
namespace boo { namespace boo {
typedef std::unordered_map<std::string, std::unique_ptr<DeviceToken>> TDeviceTokens;
typedef std::pair<TDeviceTokens::iterator, bool> TInsertedDeviceToken;
class DeviceFinder; class DeviceFinder;
using TDeviceTokens = std::unordered_map<std::string, std::unique_ptr<DeviceToken>>;
using TInsertedDeviceToken = std::pair<TDeviceTokens::iterator, bool>;
class IHIDListener { class IHIDListener {
public: public:
virtual ~IHIDListener() = default; virtual ~IHIDListener() = default;

View File

@ -23,8 +23,8 @@ struct NintendoPowerAState {
uint8_t leftY; uint8_t leftY;
uint8_t rightX; uint8_t rightX;
uint8_t rightY; uint8_t rightY;
bool operator==(const NintendoPowerAState& other); bool operator==(const NintendoPowerAState& other) const;
bool operator!=(const NintendoPowerAState& other); bool operator!=(const NintendoPowerAState& other) const;
}; };
class NintendoPowerA; class NintendoPowerA;
@ -35,14 +35,14 @@ struct INintendoPowerACallback {
class NintendoPowerA final : public TDeviceBase<INintendoPowerACallback> { class NintendoPowerA final : public TDeviceBase<INintendoPowerACallback> {
NintendoPowerAState m_last; NintendoPowerAState m_last;
void deviceDisconnected(); void deviceDisconnected() override;
void initialCycle(); void initialCycle() override;
void transferCycle(); void transferCycle() override;
void finalCycle(); void finalCycle() override;
void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message); void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override;
public: public:
NintendoPowerA(DeviceToken*); NintendoPowerA(DeviceToken*);
~NintendoPowerA(); ~NintendoPowerA() override;
}; };
} // namespace boo } // namespace boo

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
#include "DeviceBase.hpp" #include <cstdint>
#include "DeviceSignature.hpp"
#include "boo/System.hpp" #include "boo/System.hpp"
#include "boo/inputdev/DeviceBase.hpp"
#include "boo/inputdev/DeviceSignature.hpp"
namespace boo { namespace boo {
@ -36,7 +38,7 @@ class XInputPad final : public TDeviceBase<IXInputPadCallback> {
public: public:
XInputPad(DeviceToken* token) : TDeviceBase<IXInputPadCallback>(dev_typeid(XInputPad), token) {} XInputPad(DeviceToken* token) : TDeviceBase<IXInputPadCallback>(dev_typeid(XInputPad), token) {}
void deviceDisconnected() { void deviceDisconnected() override {
std::lock_guard<std::mutex> lk(m_callbackLock); std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback) if (m_callback)
m_callback->controllerDisconnected(); m_callback->controllerDisconnected();

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
#include "boo/BooObject.hpp" #include <cstddef>
#include <iterator> #include <iterator>
#include "boo/BooObject.hpp"
namespace boo { namespace boo {
/** Linked-list iterator shareable by ListNode types. */ /** Linked-list iterator shareable by ListNode types. */

View File

@ -1,14 +1,13 @@
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include "logvisor/logvisor.hpp"
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "../CFPointer.hpp" #include "lib/CFPointer.hpp"
#include <AudioToolbox/AudioToolbox.h> #include <AudioToolbox/AudioToolbox.h>
#include <CoreMIDI/CoreMIDI.h> #include <CoreMIDI/CoreMIDI.h>
#include <CoreAudio/HostTime.h> #include <CoreAudio/HostTime.h>
#include <mutex> #include <logvisor/logvisor.hpp>
#include <condition_variable>
namespace boo { namespace boo {
static logvisor::Module Log("boo::AQS"); static logvisor::Module Log("boo::AQS");
@ -74,15 +73,15 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
argSize = sizeof(devId); argSize = sizeof(devId);
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, sizeof(devName), &devName, &argSize, if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, sizeof(devName), &devName, &argSize,
&devId) != noErr) { &devId) != noErr) {
Log.report(logvisor::Error, fmt("unable to resolve audio device UID %s, using default"), Log.report(logvisor::Error, fmt("unable to resolve audio device UID {}, using default"),
CFStringGetCStringPtr(devName, kCFStringEncodingUTF8)); CFStringGetCStringPtr(devName, kCFStringEncodingUTF8));
argSize = sizeof(devId); argSize = sizeof(devId);
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice; propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &argSize, &devId) == noErr) { if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &argSize, &devId) == noErr) {
argSize = sizeof(CFStringRef); argSize = sizeof(CFStringRef);
AudioObjectPropertyAddress deviceAddress; AudioObjectPropertyAddress deviceAddress;
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID; deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
AudioObjectGetPropertyData(devId, &deviceAddress, 0, NULL, &argSize, &m_devName); AudioObjectGetPropertyData(devId, &deviceAddress, 0, nullptr, &argSize, &m_devName);
} else { } else {
Log.report(logvisor::Fatal, fmt("unable determine default audio device")); Log.report(logvisor::Fatal, fmt("unable determine default audio device"));
return {AudioChannelSet::Unknown, 48000.0}; return {AudioChannelSet::Unknown, 48000.0};
@ -90,21 +89,21 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
} }
propertyAddress.mSelector = kAudioDevicePropertyStreams; propertyAddress.mSelector = kAudioDevicePropertyStreams;
if (AudioObjectGetPropertyDataSize(devId, &propertyAddress, 0, NULL, &argSize) == noErr) { if (AudioObjectGetPropertyDataSize(devId, &propertyAddress, 0, nullptr, &argSize) == noErr) {
numStreams = argSize / sizeof(AudioStreamID); numStreams = argSize / sizeof(AudioStreamID);
streamIDs.resize(numStreams); streamIDs.resize(numStreams);
if (AudioObjectGetPropertyData(devId, &propertyAddress, 0, NULL, &argSize, &streamIDs[0]) == noErr) { if (AudioObjectGetPropertyData(devId, &propertyAddress, 0, nullptr, &argSize, &streamIDs[0]) == noErr) {
propertyAddress.mSelector = kAudioStreamPropertyDirection; propertyAddress.mSelector = kAudioStreamPropertyDirection;
for (int stm = 0; stm < numStreams; stm++) { for (int stm = 0; stm < numStreams; stm++) {
UInt32 streamDir; UInt32 streamDir;
argSize = sizeof(streamDir); argSize = sizeof(streamDir);
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, NULL, &argSize, &streamDir) == noErr) { if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, nullptr, &argSize, &streamDir) == noErr) {
if (streamDir == 0) { if (streamDir == 0) {
propertyAddress.mSelector = kAudioStreamPropertyPhysicalFormat; propertyAddress.mSelector = kAudioStreamPropertyPhysicalFormat;
AudioStreamBasicDescription asbd; AudioStreamBasicDescription asbd;
argSize = sizeof(asbd); argSize = sizeof(asbd);
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, NULL, &argSize, &asbd) == noErr) { if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, nullptr, &argSize, &asbd) == noErr) {
switch (asbd.mChannelsPerFrame) { switch (asbd.mChannelsPerFrame) {
case 2: case 2:
return {AudioChannelSet::Stereo, asbd.mSampleRate}; return {AudioChannelSet::Stereo, asbd.mSampleRate};
@ -130,9 +129,9 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return {AudioChannelSet::Unknown, 48000.0}; return {AudioChannelSet::Unknown, 48000.0};
} }
std::string getCurrentAudioOutput() const { return CFStringGetCStringPtr(m_devName.get(), kCFStringEncodingUTF8); } std::string getCurrentAudioOutput() const override { return CFStringGetCStringPtr(m_devName.get(), kCFStringEncodingUTF8); }
bool setCurrentAudioOutput(const char* name) { bool setCurrentAudioOutput(const char* name) override {
m_devName = CFPointer<CFStringRef>::adopt(CFStringCreateWithCString(nullptr, name, kCFStringEncodingUTF8)); m_devName = CFPointer<CFStringRef>::adopt(CFStringCreateWithCString(nullptr, name, kCFStringEncodingUTF8));
_rebuildAudioQueue(); _rebuildAudioQueue();
return true; return true;
@ -155,29 +154,29 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
propertyAddress.mSelector = kAudioHardwarePropertyDevices; propertyAddress.mSelector = kAudioHardwarePropertyDevices;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = kAudioObjectPropertyElementMaster; propertyAddress.mElement = kAudioObjectPropertyElementMaster;
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize) == noErr) { if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &propertySize) == noErr) {
numDevices = propertySize / sizeof(AudioDeviceID); numDevices = propertySize / sizeof(AudioDeviceID);
ret.reserve(numDevices); ret.reserve(numDevices);
deviceIDs.resize(numDevices); deviceIDs.resize(numDevices);
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &propertySize,
&deviceIDs[0]) == noErr) { &deviceIDs[0]) == noErr) {
char deviceName[64]; char deviceName[64];
for (int idx = 0; idx < numDevices; idx++) { for (int idx = 0; idx < numDevices; idx++) {
propertyAddress.mSelector = kAudioDevicePropertyStreams; propertyAddress.mSelector = kAudioDevicePropertyStreams;
if (AudioObjectGetPropertyDataSize(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize) == noErr) { if (AudioObjectGetPropertyDataSize(deviceIDs[idx], &propertyAddress, 0, nullptr, &propertySize) == noErr) {
numStreams = propertySize / sizeof(AudioStreamID); numStreams = propertySize / sizeof(AudioStreamID);
streamIDs.resize(numStreams); streamIDs.resize(numStreams);
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, &streamIDs[0]) == if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, nullptr, &propertySize, &streamIDs[0]) ==
noErr) { noErr) {
propertyAddress.mSelector = kAudioStreamPropertyDirection; propertyAddress.mSelector = kAudioStreamPropertyDirection;
bool foundOutput = false; bool foundOutput = false;
for (int stm = 0; stm < numStreams; stm++) { for (int stm = 0; stm < numStreams; stm++) {
UInt32 streamDir; UInt32 streamDir;
propertySize = sizeof(streamDir); propertySize = sizeof(streamDir);
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, NULL, &propertySize, &streamDir) == if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, nullptr, &propertySize, &streamDir) ==
noErr) { noErr) {
if (streamDir == 0) { if (streamDir == 0) {
foundOutput = true; foundOutput = true;
@ -192,13 +191,13 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
propertySize = sizeof(deviceName); propertySize = sizeof(deviceName);
propertyAddress.mSelector = kAudioDevicePropertyDeviceName; propertyAddress.mSelector = kAudioDevicePropertyDeviceName;
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, deviceName) == if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, nullptr, &propertySize, deviceName) ==
noErr) { noErr) {
CFPointer<CFStringRef> uidString; CFPointer<CFStringRef> uidString;
propertySize = sizeof(CFStringRef); propertySize = sizeof(CFStringRef);
propertyAddress.mSelector = kAudioDevicePropertyDeviceUID; propertyAddress.mSelector = kAudioDevicePropertyDeviceUID;
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, &uidString) == if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, nullptr, &propertySize, &uidString) ==
noErr) { noErr) {
ret.emplace_back(CFStringGetCStringPtr(uidString.get(), kCFStringEncodingUTF8), deviceName); ret.emplace_back(CFStringGetCStringPtr(uidString.get(), kCFStringEncodingUTF8), deviceName);
} }
@ -336,14 +335,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
MIDIIn(AQSAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver) MIDIIn(AQSAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIIn(parent, virt, std::move(receiver)) {} : IMIDIIn(parent, virt, std::move(receiver)) {}
~MIDIIn() { ~MIDIIn() override {
if (m_midi) if (m_midi)
MIDIEndpointDispose(m_midi); MIDIEndpointDispose(m_midi);
if (m_midiPort) if (m_midiPort)
MIDIPortDispose(m_midiPort); MIDIPortDispose(m_midiPort);
} }
std::string description() const { std::string description() const override {
CFPointer<CFStringRef> namestr; CFPointer<CFStringRef> namestr;
const char* nameCstr; const char* nameCstr;
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr)) if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
@ -362,14 +361,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
MIDIOut(AQSAudioVoiceEngine* parent, bool virt) : IMIDIOut(parent, virt) {} MIDIOut(AQSAudioVoiceEngine* parent, bool virt) : IMIDIOut(parent, virt) {}
~MIDIOut() { ~MIDIOut() override {
if (m_midi) if (m_midi)
MIDIEndpointDispose(m_midi); MIDIEndpointDispose(m_midi);
if (m_midiPort) if (m_midiPort)
MIDIPortDispose(m_midiPort); MIDIPortDispose(m_midiPort);
} }
std::string description() const { std::string description() const override {
CFPointer<CFStringRef> namestr; CFPointer<CFStringRef> namestr;
const char* nameCstr; const char* nameCstr;
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr)) if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
@ -381,7 +380,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return nameCstr; return nameCstr;
} }
size_t send(const void* buf, size_t len) const { size_t send(const void* buf, size_t len) const override {
union { union {
MIDIPacketList head; MIDIPacketList head;
Byte storage[512]; Byte storage[512];
@ -408,7 +407,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
MIDIInOut(AQSAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver) MIDIInOut(AQSAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIInOut(parent, virt, std::move(receiver)) {} : IMIDIInOut(parent, virt, std::move(receiver)) {}
~MIDIInOut() { ~MIDIInOut() override {
if (m_midiIn) if (m_midiIn)
MIDIEndpointDispose(m_midiIn); MIDIEndpointDispose(m_midiIn);
if (m_midiPortIn) if (m_midiPortIn)
@ -419,7 +418,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
MIDIPortDispose(m_midiPortOut); MIDIPortDispose(m_midiPortOut);
} }
std::string description() const { std::string description() const override {
CFPointer<CFStringRef> namestr; CFPointer<CFStringRef> namestr;
const char* nameCstr; const char* nameCstr;
if (MIDIObjectGetStringProperty(m_midiIn, kMIDIPropertyName, &namestr)) if (MIDIObjectGetStringProperty(m_midiIn, kMIDIPropertyName, &namestr))
@ -431,7 +430,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return nameCstr; return nameCstr;
} }
size_t send(const void* buf, size_t len) const { size_t send(const void* buf, size_t len) const override {
union { union {
MIDIPacketList head; MIDIPacketList head;
Byte storage[512]; Byte storage[512];
@ -452,7 +451,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
unsigned m_midiInCounter = 0; unsigned m_midiInCounter = 0;
unsigned m_midiOutCounter = 0; unsigned m_midiOutCounter = 0;
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) override {
if (!m_midiClient) if (!m_midiClient)
return {}; return {};
@ -477,7 +476,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() { std::unique_ptr<IMIDIOut> newVirtualMIDIOut() override {
if (!m_midiClient) if (!m_midiClient)
return {}; return {};
@ -500,7 +499,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) override {
if (!m_midiClient) if (!m_midiClient)
return {}; return {};
@ -537,7 +536,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) override {
if (!m_midiClient) if (!m_midiClient)
return {}; return {};
@ -561,7 +560,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) { std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) override {
if (!m_midiClient) if (!m_midiClient)
return {}; return {};
@ -584,7 +583,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) override {
if (!m_midiClient) if (!m_midiClient)
return {}; return {};
@ -623,7 +622,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
bool useMIDILock() const { return true; } bool useMIDILock() const override { return true; }
static void SampleRateChanged(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueuePropertyID inID) { static void SampleRateChanged(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueuePropertyID inID) {
engine->m_needsRebuild = true; engine->m_needsRebuild = true;
@ -759,7 +758,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
chMapOut.m_channels[4] = AudioChannel::FrontCenter; chMapOut.m_channels[4] = AudioChannel::FrontCenter;
break; break;
default: default:
Log.report(logvisor::Warning, fmt("unknown channel layout %u; using stereo"), layout.mChannelLayoutTag); Log.report(logvisor::Warning, fmt("unknown channel layout {}; using stereo"), layout.mChannelLayoutTag);
chMapOut.m_channelCount = 2; chMapOut.m_channelCount = 2;
chMapOut.m_channels[0] = AudioChannel::FrontLeft; chMapOut.m_channels[0] = AudioChannel::FrontLeft;
chMapOut.m_channels[1] = AudioChannel::FrontRight; chMapOut.m_channels[1] = AudioChannel::FrontRight;
@ -800,11 +799,11 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
const AudioObjectPropertyAddress* inAddresses, AQSAudioVoiceEngine* engine) { const AudioObjectPropertyAddress* inAddresses, AQSAudioVoiceEngine* engine) {
AudioObjectID defaultDeviceId; AudioObjectID defaultDeviceId;
UInt32 argSize = sizeof(defaultDeviceId); UInt32 argSize = sizeof(defaultDeviceId);
if (AudioObjectGetPropertyData(inObjectID, inAddresses, 0, NULL, &argSize, &defaultDeviceId) == noErr) { if (AudioObjectGetPropertyData(inObjectID, inAddresses, 0, nullptr, &argSize, &defaultDeviceId) == noErr) {
argSize = sizeof(CFStringRef); argSize = sizeof(CFStringRef);
AudioObjectPropertyAddress deviceAddress; AudioObjectPropertyAddress deviceAddress;
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID; deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
AudioObjectGetPropertyData(defaultDeviceId, &deviceAddress, 0, NULL, &argSize, &engine->m_devName); AudioObjectGetPropertyData(defaultDeviceId, &deviceAddress, 0, nullptr, &argSize, &engine->m_devName);
} }
engine->m_needsRebuild = true; engine->m_needsRebuild = true;
return noErr; return noErr;
@ -820,12 +819,12 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
AudioObjectID defaultDeviceId; AudioObjectID defaultDeviceId;
UInt32 argSize = sizeof(defaultDeviceId); UInt32 argSize = sizeof(defaultDeviceId);
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice; propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &argSize, &defaultDeviceId) == if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &argSize, &defaultDeviceId) ==
noErr) { noErr) {
argSize = sizeof(CFStringRef); argSize = sizeof(CFStringRef);
AudioObjectPropertyAddress deviceAddress; AudioObjectPropertyAddress deviceAddress;
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID; deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
AudioObjectGetPropertyData(defaultDeviceId, &deviceAddress, 0, NULL, &argSize, &m_devName); AudioObjectGetPropertyData(defaultDeviceId, &deviceAddress, 0, nullptr, &argSize, &m_devName);
} else { } else {
Log.report(logvisor::Fatal, fmt("unable determine default audio device")); Log.report(logvisor::Fatal, fmt("unable determine default audio device"));
return; return;
@ -841,14 +840,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
MIDIClientCreate(CFSTR("Boo MIDI"), nullptr, nullptr, &m_midiClient); MIDIClientCreate(CFSTR("Boo MIDI"), nullptr, nullptr, &m_midiClient);
} }
~AQSAudioVoiceEngine() { ~AQSAudioVoiceEngine() override {
m_cbRunning = false; m_cbRunning = false;
AudioQueueDispose(m_queue, true); AudioQueueDispose(m_queue, true);
if (m_midiClient) if (m_midiClient)
MIDIClientDispose(m_midiClient); MIDIClientDispose(m_midiClient);
} }
void pumpAndMixVoices() { void pumpAndMixVoices() override {
while (CFRunLoopRunInMode(m_runLoopMode.get(), 0, true) == kCFRunLoopRunHandledSource) {} while (CFRunLoopRunInMode(m_runLoopMode.get(), 0, true) == kCFRunLoopRunHandledSource) {}
if (m_needsRebuild) { if (m_needsRebuild) {
_rebuildAudioQueue(); _rebuildAudioQueue();

View File

@ -1,5 +1,5 @@
#include "AudioMatrix.hpp" #include "lib/audiodev/AudioMatrix.hpp"
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include <cstring> #include <cstring>
namespace boo { namespace boo {

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "boo/audiodev/IAudioVoice.hpp"
#include <vector>
#include <cstdint>
#include <limits.h>
#include <cfloat> #include <cfloat>
#include <climits>
#include <cstddef>
#include <cstdint>
#include "boo/audiodev/IAudioVoice.hpp"
#if __SSE__ #if __SSE__
#include <immintrin.h> #include <immintrin.h>

View File

@ -1,18 +1,17 @@
#include "AudioMatrix.hpp" #include "lib/audiodev/AudioMatrix.hpp"
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include <cstring>
#include <immintrin.h> #include <immintrin.h>
namespace boo { namespace boo {
typedef union { union TVectorUnion {
float v[4]; float v[4];
#if __SSE__ #if __SSE__
__m128 q; __m128 q;
__m64 d[2]; __m64 d[2];
#endif #endif
} TVectorUnion; };
static constexpr TVectorUnion Min32Vec = {{INT32_MIN, INT32_MIN, INT32_MIN, INT32_MIN}}; static constexpr TVectorUnion Min32Vec = {{INT32_MIN, INT32_MIN, INT32_MIN, INT32_MIN}};
static constexpr TVectorUnion Max32Vec = {{INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX}}; static constexpr TVectorUnion Max32Vec = {{INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX}};

View File

@ -1,7 +1,7 @@
#include "AudioSubmix.hpp" #include "lib/audiodev/AudioSubmix.hpp"
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/AudioVoice.hpp"
#include "AudioVoice.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include <cstring>
#include <algorithm> #include <algorithm>
#undef min #undef min
@ -21,9 +21,6 @@ AudioSubmix*& AudioSubmix::_getHeadPtr(BaseAudioVoiceEngine* head) { return head
std::unique_lock<std::recursive_mutex> AudioSubmix::_getHeadLock(BaseAudioVoiceEngine* head) { std::unique_lock<std::recursive_mutex> AudioSubmix::_getHeadLock(BaseAudioVoiceEngine* head) {
return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; return std::unique_lock<std::recursive_mutex>{head->m_dataMutex};
} }
std::unique_lock<std::recursive_mutex> AudioSubmix::destructorLock() {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
bool AudioSubmix::_isDirectDependencyOf(AudioSubmix* send) { return m_sendGains.find(send) != m_sendGains.cend(); } bool AudioSubmix::_isDirectDependencyOf(AudioSubmix* send) { return m_sendGains.find(send) != m_sendGains.cend(); }

View File

@ -1,11 +1,15 @@
#pragma once #pragma once
#include "boo/audiodev/IAudioSubmix.hpp"
#include <list>
#include <vector>
#include <array> #include <array>
#include <cstddef>
#include <cstdint>
#include <list>
#include <mutex>
#include <unordered_map> #include <unordered_map>
#include "Common.hpp" #include <vector>
#include "boo/audiodev/IAudioSubmix.hpp"
#include "lib/audiodev/Common.hpp"
#if __SSE__ #if __SSE__
#include <immintrin.h> #include <immintrin.h>
@ -80,16 +84,15 @@ class AudioSubmix : public ListNode<AudioSubmix, BaseAudioVoiceEngine*, IAudioSu
public: public:
static AudioSubmix*& _getHeadPtr(BaseAudioVoiceEngine* head); static AudioSubmix*& _getHeadPtr(BaseAudioVoiceEngine* head);
static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head); static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head);
std::unique_lock<std::recursive_mutex> destructorLock();
AudioSubmix(BaseAudioVoiceEngine& root, IAudioSubmixCallback* cb, int busId, bool mainOut); AudioSubmix(BaseAudioVoiceEngine& root, IAudioSubmixCallback* cb, int busId, bool mainOut);
~AudioSubmix(); ~AudioSubmix() override;
void resetSendLevels(); void resetSendLevels() override;
void setSendLevel(IAudioSubmix* submix, float level, bool slew); void setSendLevel(IAudioSubmix* submix, float level, bool slew) override;
const AudioVoiceEngineMixInfo& mixInfo() const; const AudioVoiceEngineMixInfo& mixInfo() const;
double getSampleRate() const; double getSampleRate() const override;
SubmixFormat getSampleFormat() const; SubmixFormat getSampleFormat() const override;
}; };
template <> template <>

View File

@ -18,9 +18,6 @@ AudioVoice*& AudioVoice::_getHeadPtr(BaseAudioVoiceEngine* head) { return head->
std::unique_lock<std::recursive_mutex> AudioVoice::_getHeadLock(BaseAudioVoiceEngine* head) { std::unique_lock<std::recursive_mutex> AudioVoice::_getHeadLock(BaseAudioVoiceEngine* head) {
return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; return std::unique_lock<std::recursive_mutex>{head->m_dataMutex};
} }
std::unique_lock<std::recursive_mutex> AudioVoice::destructorLock() {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
void AudioVoice::_setPitchRatio(double ratio, bool slew) { void AudioVoice::_setPitchRatio(double ratio, bool slew) {
if (m_dynamicRate) { if (m_dynamicRate) {

View File

@ -1,12 +1,14 @@
#pragma once #pragma once
#include <soxr.h> #include <mutex>
#include <list>
#include <unordered_map> #include <unordered_map>
#include "boo/audiodev/IAudioVoice.hpp" #include "boo/audiodev/IAudioVoice.hpp"
#include "AudioMatrix.hpp" #include "lib/audiodev/AudioMatrix.hpp"
#include "Common.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/Common.hpp"
#include <soxr.h>
struct AudioUnitVoiceEngine; struct AudioUnitVoiceEngine;
struct VSTVoiceEngine; struct VSTVoiceEngine;
@ -64,13 +66,12 @@ protected:
public: public:
static AudioVoice*& _getHeadPtr(BaseAudioVoiceEngine* head); static AudioVoice*& _getHeadPtr(BaseAudioVoiceEngine* head);
static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head); static std::unique_lock<std::recursive_mutex> _getHeadLock(BaseAudioVoiceEngine* head);
std::unique_lock<std::recursive_mutex> destructorLock();
~AudioVoice(); ~AudioVoice() override;
void resetSampleRate(double sampleRate); void resetSampleRate(double sampleRate) override;
void setPitchRatio(double ratio, bool slew); void setPitchRatio(double ratio, bool slew) override;
void start(); void start() override;
void stop(); void stop() override;
double getSampleRateIn() const { return m_sampleRateIn; } double getSampleRateIn() const { return m_sampleRateIn; }
double getSampleRateOut() const { return m_sampleRateOut; } double getSampleRateOut() const { return m_sampleRateOut; }
}; };
@ -91,7 +92,7 @@ inline size_t AudioVoice::pumpAndMix<float>(size_t frames) {
class AudioVoiceMono : public AudioVoice { class AudioVoiceMono : public AudioVoice {
std::unordered_map<IAudioSubmix*, AudioMatrixMono> m_sendMatrices; std::unordered_map<IAudioSubmix*, AudioMatrixMono> m_sendMatrices;
bool m_silentOut = false; bool m_silentOut = false;
void _resetSampleRate(double sampleRate); void _resetSampleRate(double sampleRate) override;
static size_t SRCCallback(AudioVoiceMono* ctx, int16_t** data, size_t requestedLen); static size_t SRCCallback(AudioVoiceMono* ctx, int16_t** data, size_t requestedLen);
@ -99,21 +100,21 @@ class AudioVoiceMono : public AudioVoice {
template <typename T> template <typename T>
size_t _pumpAndMix(size_t frames); size_t _pumpAndMix(size_t frames);
size_t pumpAndMix16(size_t frames) { return _pumpAndMix<int16_t>(frames); } size_t pumpAndMix16(size_t frames) override { return _pumpAndMix<int16_t>(frames); }
size_t pumpAndMix32(size_t frames) { return _pumpAndMix<int32_t>(frames); } size_t pumpAndMix32(size_t frames) override { return _pumpAndMix<int32_t>(frames); }
size_t pumpAndMixFlt(size_t frames) { return _pumpAndMix<float>(frames); } size_t pumpAndMixFlt(size_t frames) override { return _pumpAndMix<float>(frames); }
public: public:
AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate, bool dynamicRate); AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate, bool dynamicRate);
void resetChannelLevels(); void resetChannelLevels() override;
void setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew); void setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew) override;
void setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew); void setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew) override;
}; };
class AudioVoiceStereo : public AudioVoice { class AudioVoiceStereo : public AudioVoice {
std::unordered_map<IAudioSubmix*, AudioMatrixStereo> m_sendMatrices; std::unordered_map<IAudioSubmix*, AudioMatrixStereo> m_sendMatrices;
bool m_silentOut = false; bool m_silentOut = false;
void _resetSampleRate(double sampleRate); void _resetSampleRate(double sampleRate) override;
static size_t SRCCallback(AudioVoiceStereo* ctx, int16_t** data, size_t requestedLen); static size_t SRCCallback(AudioVoiceStereo* ctx, int16_t** data, size_t requestedLen);
@ -121,15 +122,15 @@ class AudioVoiceStereo : public AudioVoice {
template <typename T> template <typename T>
size_t _pumpAndMix(size_t frames); size_t _pumpAndMix(size_t frames);
size_t pumpAndMix16(size_t frames) { return _pumpAndMix<int16_t>(frames); } size_t pumpAndMix16(size_t frames) override { return _pumpAndMix<int16_t>(frames); }
size_t pumpAndMix32(size_t frames) { return _pumpAndMix<int32_t>(frames); } size_t pumpAndMix32(size_t frames) override { return _pumpAndMix<int32_t>(frames); }
size_t pumpAndMixFlt(size_t frames) { return _pumpAndMix<float>(frames); } size_t pumpAndMixFlt(size_t frames) override { return _pumpAndMix<float>(frames); }
public: public:
AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate, bool dynamicRate); AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate, bool dynamicRate);
void resetChannelLevels(); void resetChannelLevels() override;
void setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew); void setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew) override;
void setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew); void setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew) override;
}; };
} // namespace boo } // namespace boo

View File

@ -1,5 +1,7 @@
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include <cassert> #include <cassert>
#include <cstring>
namespace boo { namespace boo {

View File

@ -1,12 +1,18 @@
#pragma once #pragma once
#include "boo/audiodev/IAudioVoiceEngine.hpp" #include <cstddef>
#include "LtRtProcessing.hpp" #include <cstdint>
#include "Common.hpp" #include <list>
#include "AudioVoice.hpp" #include <memory>
#include "AudioSubmix.hpp"
#include <functional>
#include <mutex> #include <mutex>
#include <vector>
#include "boo/BooObject.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "lib/audiodev/AudioSubmix.hpp"
#include "lib/audiodev/AudioVoice.hpp"
#include "lib/audiodev/Common.hpp"
#include "lib/audiodev/LtRtProcessing.hpp"
namespace boo { namespace boo {
@ -57,22 +63,24 @@ protected:
public: public:
BaseAudioVoiceEngine() : m_mainSubmix(std::make_unique<AudioSubmix>(*this, nullptr, -1, false)) {} BaseAudioVoiceEngine() : m_mainSubmix(std::make_unique<AudioSubmix>(*this, nullptr, -1, false)) {}
~BaseAudioVoiceEngine(); ~BaseAudioVoiceEngine() override;
ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate, IAudioVoiceCallback* cb, bool dynamicPitch = false); ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate, IAudioVoiceCallback* cb,
bool dynamicPitch = false) override;
ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate, IAudioVoiceCallback* cb, bool dynamicPitch = false); ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate, IAudioVoiceCallback* cb,
bool dynamicPitch = false) override;
ObjToken<IAudioSubmix> allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId); ObjToken<IAudioSubmix> allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId) override;
void setCallbackInterface(IAudioVoiceEngineCallback* cb); void setCallbackInterface(IAudioVoiceEngineCallback* cb) override;
void setVolume(float vol); void setVolume(float vol) override;
bool enableLtRt(bool enable); bool enableLtRt(bool enable) override;
const AudioVoiceEngineMixInfo& mixInfo() const; const AudioVoiceEngineMixInfo& mixInfo() const;
const AudioVoiceEngineMixInfo& clientMixInfo() const; const AudioVoiceEngineMixInfo& clientMixInfo() const;
AudioChannelSet getAvailableSet() { return clientMixInfo().m_channels; } AudioChannelSet getAvailableSet() override { return clientMixInfo().m_channels; }
void pumpAndMixVoices() {} void pumpAndMixVoices() override {}
size_t get5MsFrames() const { return m_5msFrames; } size_t get5MsFrames() const override { return m_5msFrames; }
}; };
template <> template <>

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <soxr.h> #include <soxr.h>
#include "../Common.hpp"
#include "boo/audiodev/IAudioVoice.hpp" #include "boo/audiodev/IAudioVoice.hpp"
#include "lib/Common.hpp"
namespace boo { namespace boo {

View File

@ -1,11 +1,13 @@
#pragma once #pragma once
#include "AudioVoiceEngine.hpp" #include <csignal>
#include "logvisor/logvisor.hpp"
#include <thread> #include <thread>
#include <unordered_map>
#include "lib/audiodev/AudioVoiceEngine.hpp"
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include <signal.h> #include <logvisor/logvisor.hpp>
namespace boo { namespace boo {
extern logvisor::Module ALSALog; extern logvisor::Module ALSALog;
@ -25,12 +27,12 @@ struct LinuxMidi : BaseAudioVoiceEngine {
} }
} }
~LinuxMidi() { ~LinuxMidi() override {
for (auto& p : m_openHandles) for (auto& p : m_openHandles)
p.second->_disown(); p.second->_disown();
} }
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const { std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const override {
std::vector<std::pair<std::string, std::string>> ret; std::vector<std::pair<std::string, std::string>> ret;
int status; int status;
int card = -1; /* use -1 to prime the pump of iterating through card list */ int card = -1; /* use -1 to prime the pump of iterating through card list */
@ -83,7 +85,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return ret; return ret;
} }
bool supportsVirtualMIDIIn() const { return true; } bool supportsVirtualMIDIIn() const override { return true; }
static void MIDIFreeProc(void* midiStatus) { snd_rawmidi_status_free((snd_rawmidi_status_t*)midiStatus); } static void MIDIFreeProc(void* midiStatus) { snd_rawmidi_status_free((snd_rawmidi_status_t*)midiStatus); }
@ -126,7 +128,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
, m_midi(midi) , m_midi(midi)
, m_midiThread(std::bind(MIDIReceiveProc, m_midi, m_receiver)) {} , m_midiThread(std::bind(MIDIReceiveProc, m_midi, m_receiver)) {}
~MIDIIn() { ~MIDIIn() override {
if (m_parent) if (m_parent)
static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this); static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this);
pthread_cancel(m_midiThread.native_handle()); pthread_cancel(m_midiThread.native_handle());
@ -135,7 +137,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
snd_rawmidi_close(m_midi); snd_rawmidi_close(m_midi);
} }
std::string description() const { std::string description() const override {
snd_rawmidi_info_t* info; snd_rawmidi_info_t* info;
snd_rawmidi_info_alloca(&info); snd_rawmidi_info_alloca(&info);
snd_rawmidi_info(m_midi, info); snd_rawmidi_info(m_midi, info);
@ -148,13 +150,13 @@ struct LinuxMidi : BaseAudioVoiceEngine {
snd_rawmidi_t* m_midi; snd_rawmidi_t* m_midi;
MIDIOut(LinuxMidi* parent, snd_rawmidi_t* midi, bool virt) : IMIDIOut(parent, virt), m_midi(midi) {} MIDIOut(LinuxMidi* parent, snd_rawmidi_t* midi, bool virt) : IMIDIOut(parent, virt), m_midi(midi) {}
~MIDIOut() { ~MIDIOut() override {
if (m_parent) if (m_parent)
static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this); static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this);
snd_rawmidi_close(m_midi); snd_rawmidi_close(m_midi);
} }
std::string description() const { std::string description() const override {
snd_rawmidi_info_t* info; snd_rawmidi_info_t* info;
snd_rawmidi_info_alloca(&info); snd_rawmidi_info_alloca(&info);
snd_rawmidi_info(m_midi, info); snd_rawmidi_info(m_midi, info);
@ -162,7 +164,9 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return ret; return ret;
} }
size_t send(const void* buf, size_t len) const { return size_t(std::max(0l, snd_rawmidi_write(m_midi, buf, len))); } size_t send(const void* buf, size_t len) const override {
return size_t(std::max(0l, snd_rawmidi_write(m_midi, buf, len)));
}
}; };
struct MIDIInOut : public IMIDIInOut { struct MIDIInOut : public IMIDIInOut {
@ -176,7 +180,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
, m_midiOut(midiOut) , m_midiOut(midiOut)
, m_midiThread(std::bind(MIDIReceiveProc, m_midiIn, m_receiver)) {} , m_midiThread(std::bind(MIDIReceiveProc, m_midiIn, m_receiver)) {}
~MIDIInOut() { ~MIDIInOut() override {
if (m_parent) if (m_parent)
static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this); static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this);
pthread_cancel(m_midiThread.native_handle()); pthread_cancel(m_midiThread.native_handle());
@ -186,7 +190,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
snd_rawmidi_close(m_midiOut); snd_rawmidi_close(m_midiOut);
} }
std::string description() const { std::string description() const override {
snd_rawmidi_info_t* info; snd_rawmidi_info_t* info;
snd_rawmidi_info_alloca(&info); snd_rawmidi_info_alloca(&info);
snd_rawmidi_info(m_midiIn, info); snd_rawmidi_info(m_midiIn, info);
@ -194,12 +198,12 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return ret; return ret;
} }
size_t send(const void* buf, size_t len) const { size_t send(const void* buf, size_t len) const override {
return size_t(std::max(0l, snd_rawmidi_write(m_midiOut, buf, len))); return size_t(std::max(0l, snd_rawmidi_write(m_midiOut, buf, len)));
} }
}; };
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) override {
int status; int status;
snd_rawmidi_t* midi; snd_rawmidi_t* midi;
status = snd_rawmidi_open(&midi, nullptr, "virtual", 0); status = snd_rawmidi_open(&midi, nullptr, "virtual", 0);
@ -208,7 +212,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return std::make_unique<MIDIIn>(nullptr, midi, true, std::move(receiver)); return std::make_unique<MIDIIn>(nullptr, midi, true, std::move(receiver));
} }
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() { std::unique_ptr<IMIDIOut> newVirtualMIDIOut() override {
int status; int status;
snd_rawmidi_t* midi; snd_rawmidi_t* midi;
status = snd_rawmidi_open(nullptr, &midi, "virtual", 0); status = snd_rawmidi_open(nullptr, &midi, "virtual", 0);
@ -217,7 +221,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return std::make_unique<MIDIOut>(nullptr, midi, true); return std::make_unique<MIDIOut>(nullptr, midi, true);
} }
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) override {
int status; int status;
snd_rawmidi_t* midiIn; snd_rawmidi_t* midiIn;
snd_rawmidi_t* midiOut; snd_rawmidi_t* midiOut;
@ -227,7 +231,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return std::make_unique<MIDIInOut>(nullptr, midiIn, midiOut, true, std::move(receiver)); return std::make_unique<MIDIInOut>(nullptr, midiIn, midiOut, true, std::move(receiver));
} }
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) override {
snd_rawmidi_t* midi; snd_rawmidi_t* midi;
int status = snd_rawmidi_open(&midi, nullptr, name, 0); int status = snd_rawmidi_open(&midi, nullptr, name, 0);
if (status) if (status)
@ -237,7 +241,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) { std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) override {
snd_rawmidi_t* midi; snd_rawmidi_t* midi;
int status = snd_rawmidi_open(nullptr, &midi, name, 0); int status = snd_rawmidi_open(nullptr, &midi, name, 0);
if (status) if (status)
@ -247,7 +251,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) override {
snd_rawmidi_t* midiIn; snd_rawmidi_t* midiIn;
snd_rawmidi_t* midiOut; snd_rawmidi_t* midiOut;
int status = snd_rawmidi_open(&midiIn, &midiOut, name, 0); int status = snd_rawmidi_open(&midiIn, &midiOut, name, 0);
@ -258,7 +262,7 @@ struct LinuxMidi : BaseAudioVoiceEngine {
return ret; return ret;
} }
bool useMIDILock() const { return true; } bool useMIDILock() const override { return true; }
}; };
} // namespace boo } // namespace boo

View File

@ -1,16 +1,17 @@
#include "LtRtProcessing.hpp" #include "lib/audiodev/LtRtProcessing.hpp"
#include <cmath>
#include <algorithm> #include <algorithm>
#include <cmath>
#undef min #undef min
#undef max #undef max
namespace boo { namespace boo {
namespace {
template <typename T> template <typename T>
inline T ClampFull(float in) { constexpr T ClampFull(float in) {
if (std::is_floating_point<T>()) { if constexpr (std::is_floating_point_v<T>) {
return std::min<T>(std::max<T>(in, -1.f), 1.f); return std::clamp(in, -1.f, 1.f);
} else { } else {
constexpr T MAX = std::numeric_limits<T>::max(); constexpr T MAX = std::numeric_limits<T>::max();
constexpr T MIN = std::numeric_limits<T>::min(); constexpr T MIN = std::numeric_limits<T>::min();
@ -23,6 +24,7 @@ inline T ClampFull(float in) {
return in; return in;
} }
} }
} // Anonymous namespace
#if INTEL_IPP #if INTEL_IPP
@ -237,19 +239,16 @@ LtRtProcessing::LtRtProcessing(int _5msFrames, const AudioVoiceEngineMixInfo& mi
m_inMixInfo.m_channelMap.m_channels[3] = AudioChannel::RearLeft; m_inMixInfo.m_channelMap.m_channels[3] = AudioChannel::RearLeft;
m_inMixInfo.m_channelMap.m_channels[4] = AudioChannel::RearRight; m_inMixInfo.m_channelMap.m_channels[4] = AudioChannel::RearRight;
int samples = m_windowFrames * (5 * 2 + 2 * 2); const int samples = m_windowFrames * (5 * 2 + 2 * 2);
switch (mixInfo.m_sampleFormat) { switch (mixInfo.m_sampleFormat) {
case SOXR_INT16_I: case SOXR_INT16_I:
m_16Buffer.reset(new int16_t[samples]); m_16Buffer = std::make_unique<int16_t[]>(samples);
memset(m_16Buffer.get(), 0, sizeof(int16_t) * samples);
break; break;
case SOXR_INT32_I: case SOXR_INT32_I:
m_32Buffer.reset(new int32_t[samples]); m_32Buffer = std::make_unique<int32_t[]>(samples);
memset(m_32Buffer.get(), 0, sizeof(int32_t) * samples);
break; break;
case SOXR_FLOAT32_I: case SOXR_FLOAT32_I:
m_fltBuffer.reset(new float[samples]); m_fltBuffer = std::make_unique<float[]>(samples);
memset(m_fltBuffer.get(), 0, sizeof(float) * samples);
break; break;
default: default:
break; break;
@ -259,12 +258,12 @@ LtRtProcessing::LtRtProcessing(int _5msFrames, const AudioVoiceEngineMixInfo& mi
template <typename T> template <typename T>
void LtRtProcessing::Process(const T* input, T* output, int frameCount) { void LtRtProcessing::Process(const T* input, T* output, int frameCount) {
#if 0 #if 0
for (int i=0 ; i<frameCount ; ++i) for (int i = 0; i < frameCount; ++i)
{ {
output[i * 2] = input[i * 5 + 3]; output[i * 2] = input[i * 5 + 3];
output[i * 2 + 1] = input[i * 5 + 4]; output[i * 2 + 1] = input[i * 5 + 4];
} }
return; return;
#endif #endif
int outFramesRem = frameCount; int outFramesRem = frameCount;
@ -273,14 +272,14 @@ void LtRtProcessing::Process(const T* input, T* output, int frameCount) {
int tail = std::min(m_windowFrames * 2, m_bufferTail + frameCount); int tail = std::min(m_windowFrames * 2, m_bufferTail + frameCount);
int samples = (tail - m_bufferTail) * 5; int samples = (tail - m_bufferTail) * 5;
memmove(&inBuf[m_bufferTail * 5], input, samples * sizeof(T)); memmove(&inBuf[m_bufferTail * 5], input, samples * sizeof(T));
// printf("input %d to %d\n", tail - m_bufferTail, m_bufferTail); // fmt::print("input {} to {}\n", tail - m_bufferTail, m_bufferTail);
input += samples; input += samples;
frameCount -= tail - m_bufferTail; frameCount -= tail - m_bufferTail;
int head = std::min(m_windowFrames * 2, m_bufferHead + outFramesRem); int head = std::min(m_windowFrames * 2, m_bufferHead + outFramesRem);
samples = (head - m_bufferHead) * 2; samples = (head - m_bufferHead) * 2;
memmove(output, outBuf + m_bufferHead * 2, samples * sizeof(T)); memmove(output, outBuf + m_bufferHead * 2, samples * sizeof(T));
// printf("output %d from %d\n", head - m_bufferHead, m_bufferHead); // fmt::print("output {} from {}\n", head - m_bufferHead, m_bufferHead);
output += samples; output += samples;
outFramesRem -= head - m_bufferHead; outFramesRem -= head - m_bufferHead;
@ -300,7 +299,7 @@ void LtRtProcessing::Process(const T* input, T* output, int frameCount) {
for (int i = 0; i < m_windowFrames; ++i, ++delayI) { for (int i = 0; i < m_windowFrames; ++i, ++delayI) {
out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]); out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]);
out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]); out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]);
// printf("in %d out %d\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i); // fmt::print("in {} out {}\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i);
} }
} else { } else {
int delayI = m_windowFrames * 2 - m_halfFrames; int delayI = m_windowFrames * 2 - m_halfFrames;
@ -308,13 +307,13 @@ void LtRtProcessing::Process(const T* input, T* output, int frameCount) {
for (i = 0; i < m_halfFrames; ++i, ++delayI) { for (i = 0; i < m_halfFrames; ++i, ++delayI) {
out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]); out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]);
out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]); out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]);
// printf("in %d out %d\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i); // fmt::print("in {} out {}\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i);
} }
delayI = 0; delayI = 0;
for (; i < m_windowFrames; ++i, ++delayI) { for (; i < m_windowFrames; ++i, ++delayI) {
out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]); out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]);
out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]); out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]);
// printf("in %d out %d\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i); // fmt::print("in {} out {}\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i);
} }
} }
#if INTEL_IPP #if INTEL_IPP
@ -328,14 +327,14 @@ void LtRtProcessing::Process(const T* input, T* output, int frameCount) {
if (frameCount) { if (frameCount) {
samples = frameCount * 5; samples = frameCount * 5;
memmove(inBuf, input, samples * sizeof(T)); memmove(inBuf, input, samples * sizeof(T));
// printf("input %d to %d\n", frameCount, 0); // fmt::print("input {} to {}\n", frameCount, 0);
m_bufferTail = frameCount; m_bufferTail = frameCount;
} }
if (outFramesRem) { if (outFramesRem) {
samples = outFramesRem * 2; samples = outFramesRem * 2;
memmove(output, outBuf, samples * sizeof(T)); memmove(output, outBuf, samples * sizeof(T));
// printf("output %d from %d\n", outFramesRem, 0); // fmt::print("output {} from {}\n", outFramesRem, 0);
m_bufferHead = outFramesRem; m_bufferHead = outFramesRem;
} }
} }

View File

@ -1,9 +1,11 @@
#pragma once #pragma once
#include <cstdint>
#include <memory>
#include "boo/System.hpp" #include "boo/System.hpp"
#include "boo/audiodev/IAudioVoice.hpp" #include "boo/audiodev/IAudioVoice.hpp"
#include "Common.hpp" #include "lib/audiodev/Common.hpp"
#include <memory>
#if INTEL_IPP #if INTEL_IPP
#include "ipp.h" #include "ipp.h"

View File

@ -1,4 +1,5 @@
#include "MIDICommon.hpp" #include "lib/audiodev/MIDICommon.hpp"
#include "boo/audiodev/IMIDIPort.hpp" #include "boo/audiodev/IMIDIPort.hpp"
namespace boo { namespace boo {

View File

@ -1,39 +1,46 @@
#include "boo/audiodev/MIDIDecoder.hpp" #include "boo/audiodev/MIDIDecoder.hpp"
#include "MIDICommon.hpp"
#include <memory>
#include <algorithm> #include <algorithm>
#include <optional>
#include "boo/audiodev/IMIDIReader.hpp"
#include "lib/audiodev/MIDICommon.hpp"
namespace boo { namespace boo {
namespace {
constexpr uint8_t clamp7(uint8_t val) { return std::clamp(val, uint8_t{0}, uint8_t{127}); }
constexpr uint8_t clamp7(uint8_t val) { return std::max(0, std::min(127, int(val))); } std::optional<uint32_t> readContinuedValue(std::vector<uint8_t>::const_iterator& it,
std::vector<uint8_t>::const_iterator end) {
bool MIDIDecoder::_readContinuedValue(std::vector<uint8_t>::const_iterator& it,
std::vector<uint8_t>::const_iterator end, uint32_t& valOut) {
uint8_t a = *it++; uint8_t a = *it++;
valOut = a & 0x7f; uint32_t valOut = a & 0x7f;
if (a & 0x80) { if ((a & 0x80) != 0) {
if (it == end) if (it == end) {
return false; return std::nullopt;
}
valOut <<= 7; valOut <<= 7;
a = *it++; a = *it++;
valOut |= a & 0x7f; valOut |= a & 0x7f;
if (a & 0x80) { if ((a & 0x80) != 0) {
if (it == end) if (it == end) {
return false; return std::nullopt;
}
valOut <<= 7; valOut <<= 7;
a = *it++; a = *it++;
valOut |= a & 0x7f; valOut |= a & 0x7f;
} }
} }
return true; return valOut;
} }
} // Anonymous namespace
std::vector<uint8_t>::const_iterator MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin, std::vector<uint8_t>::const_iterator MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
std::vector<uint8_t>::const_iterator end) { std::vector<uint8_t>::const_iterator end) {
std::vector<uint8_t>::const_iterator it = begin; auto it = begin;
while (it != end) { while (it != end) {
uint8_t a = *it++; uint8_t a = *it++;
uint8_t b; uint8_t b;
@ -48,9 +55,8 @@ std::vector<uint8_t>::const_iterator MIDIDecoder::receiveBytes(std::vector<uint8
return begin; return begin;
a = *it++; a = *it++;
uint32_t length; const auto length = readContinuedValue(it, end);
_readContinuedValue(it, end, length); it += *length;
it += length;
} else { } else {
uint8_t chan = m_status & 0xf; uint8_t chan = m_status & 0xf;
switch (Status(m_status & 0xf0)) { switch (Status(m_status & 0xf0)) {
@ -121,10 +127,11 @@ std::vector<uint8_t>::const_iterator MIDIDecoder::receiveBytes(std::vector<uint8
case Status::SysEx: { case Status::SysEx: {
switch (Status(m_status & 0xff)) { switch (Status(m_status & 0xff)) {
case Status::SysEx: { case Status::SysEx: {
uint32_t len; const auto len = readContinuedValue(it, end);
if (!_readContinuedValue(it, end, len) || end - it < len) if (!len || end - it < *len) {
return begin; return begin;
m_out.sysex(&*it, len); }
m_out.sysex(&*it, *len);
break; break;
} }
case Status::TimecodeQuarterFrame: { case Status::TimecodeQuarterFrame: {

View File

@ -1,7 +1,17 @@
#include "boo/audiodev/MIDIEncoder.hpp" #include "boo/audiodev/MIDIEncoder.hpp"
#include "MIDICommon.hpp"
#include <array>
#include "boo/audiodev/IMIDIPort.hpp"
#include "lib/audiodev/MIDICommon.hpp"
namespace boo { namespace boo {
namespace {
template <typename... Args>
constexpr auto MakeCommand(Args&&... args) -> std::array<uint8_t, sizeof...(Args)> {
return {std::forward<Args>(args)...};
}
} // Anonymous namespace
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::_sendMessage(const uint8_t* data, size_t len) { void MIDIEncoder<Sender>::_sendMessage(const uint8_t* data, size_t len) {
@ -16,7 +26,7 @@ void MIDIEncoder<Sender>::_sendMessage(const uint8_t* data, size_t len) {
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::_sendContinuedValue(uint32_t val) { void MIDIEncoder<Sender>::_sendContinuedValue(uint32_t val) {
uint8_t send[3] = {}; std::array<uint8_t, 3> send{};
uint8_t* ptr = nullptr; uint8_t* ptr = nullptr;
if (val >= 0x4000) { if (val >= 0x4000) {
ptr = &send[0]; ptr = &send[0];
@ -26,154 +36,164 @@ void MIDIEncoder<Sender>::_sendContinuedValue(uint32_t val) {
} }
if (val >= 0x80) { if (val >= 0x80) {
if (!ptr) if (ptr == nullptr) {
ptr = &send[1]; ptr = &send[1];
}
send[1] = 0x80 | ((val / 0x80) & 0x7f); send[1] = 0x80 | ((val / 0x80) & 0x7f);
} }
if (!ptr) if (ptr == nullptr) {
ptr = &send[2]; ptr = &send[2];
}
send[2] = val & 0x7f; send[2] = val & 0x7f;
m_sender.send(ptr, 3 - (ptr - send)); const size_t sendLength = send.size() - (ptr - send.data());
m_sender.send(ptr, sendLength);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) { void MIDIEncoder<Sender>::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) {
uint8_t cmd[3] = {uint8_t(int(Status::NoteOff) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)}; const auto cmd =
_sendMessage(cmd, 3); MakeCommand(uint8_t(int(Status::NoteOff) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f));
_sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) { void MIDIEncoder<Sender>::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) {
uint8_t cmd[3] = {uint8_t(int(Status::NoteOn) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)}; const auto cmd =
_sendMessage(cmd, 3); MakeCommand(uint8_t(int(Status::NoteOn) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f));
_sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::notePressure(uint8_t chan, uint8_t key, uint8_t pressure) { void MIDIEncoder<Sender>::notePressure(uint8_t chan, uint8_t key, uint8_t pressure) {
uint8_t cmd[3] = {uint8_t(int(Status::NotePressure) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(pressure & 0x7f)}; const auto cmd =
_sendMessage(cmd, 3); MakeCommand(uint8_t(int(Status::NotePressure) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(pressure & 0x7f));
_sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::controlChange(uint8_t chan, uint8_t control, uint8_t value) { void MIDIEncoder<Sender>::controlChange(uint8_t chan, uint8_t control, uint8_t value) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(control & 0x7f), uint8_t(value & 0x7f)}; const auto cmd =
_sendMessage(cmd, 3); MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(control & 0x7f), uint8_t(value & 0x7f));
_sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::programChange(uint8_t chan, uint8_t program) { void MIDIEncoder<Sender>::programChange(uint8_t chan, uint8_t program) {
uint8_t cmd[2] = {uint8_t(int(Status::ProgramChange) | (chan & 0xf)), uint8_t(program & 0x7f)}; const auto cmd = MakeCommand(uint8_t(int(Status::ProgramChange) | (chan & 0xf)), uint8_t(program & 0x7f));
_sendMessage(cmd, 2); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::channelPressure(uint8_t chan, uint8_t pressure) { void MIDIEncoder<Sender>::channelPressure(uint8_t chan, uint8_t pressure) {
uint8_t cmd[2] = {uint8_t(int(Status::ChannelPressure) | (chan & 0xf)), uint8_t(pressure & 0x7f)}; const auto cmd = MakeCommand(uint8_t(int(Status::ChannelPressure) | (chan & 0xf)), uint8_t(pressure & 0x7f));
_sendMessage(cmd, 2); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::pitchBend(uint8_t chan, int16_t pitch) { void MIDIEncoder<Sender>::pitchBend(uint8_t chan, int16_t pitch) {
uint8_t cmd[3] = {uint8_t(int(Status::PitchBend) | (chan & 0xf)), uint8_t((pitch % 128) & 0x7f), const auto cmd = MakeCommand(uint8_t(int(Status::PitchBend) | (chan & 0xf)), uint8_t((pitch % 128) & 0x7f),
uint8_t((pitch / 128) & 0x7f)}; uint8_t((pitch / 128) & 0x7f));
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::allSoundOff(uint8_t chan) { void MIDIEncoder<Sender>::allSoundOff(uint8_t chan) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 120, 0}; const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{120}, uint8_t{0});
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::resetAllControllers(uint8_t chan) { void MIDIEncoder<Sender>::resetAllControllers(uint8_t chan) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 121, 0}; const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{121}, uint8_t{0});
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::localControl(uint8_t chan, bool on) { void MIDIEncoder<Sender>::localControl(uint8_t chan, bool on) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 122, uint8_t(on ? 127 : 0)}; const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{122}, uint8_t(on ? 127 : 0));
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::allNotesOff(uint8_t chan) { void MIDIEncoder<Sender>::allNotesOff(uint8_t chan) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 123, 0}; const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{123}, uint8_t{0});
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::omniMode(uint8_t chan, bool on) { void MIDIEncoder<Sender>::omniMode(uint8_t chan, bool on) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 125 : 124), 0}; const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 125 : 124), uint8_t{0});
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::polyMode(uint8_t chan, bool on) { void MIDIEncoder<Sender>::polyMode(uint8_t chan, bool on) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 127 : 126), 0}; const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 127 : 126), uint8_t{0});
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::sysex(const void* data, size_t len) { void MIDIEncoder<Sender>::sysex(const void* data, size_t len) {
uint8_t cmd = uint8_t(Status::SysEx); constexpr auto sysexCmd = MakeCommand(uint8_t(Status::SysEx));
_sendMessage(&cmd, 1); _sendMessage(sysexCmd);
_sendContinuedValue(len); _sendContinuedValue(len);
m_sender.send(data, len); m_sender.send(data, len);
cmd = uint8_t(Status::SysExTerm);
_sendMessage(&cmd, 1); constexpr auto sysexTermCmd = MakeCommand(uint8_t(Status::SysExTerm));
_sendMessage(sysexTermCmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::timeCodeQuarterFrame(uint8_t message, uint8_t value) { void MIDIEncoder<Sender>::timeCodeQuarterFrame(uint8_t message, uint8_t value) {
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t((message & 0x7 << 4) | (value & 0xf))}; const auto cmd =
_sendMessage(cmd, 2); MakeCommand(uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t((message & 0x7 << 4) | (value & 0xf)));
_sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::songPositionPointer(uint16_t pointer) { void MIDIEncoder<Sender>::songPositionPointer(uint16_t pointer) {
uint8_t cmd[3] = {uint8_t(int(Status::SongPositionPointer)), uint8_t((pointer % 128) & 0x7f), const auto cmd = MakeCommand(uint8_t(int(Status::SongPositionPointer)), uint8_t((pointer % 128) & 0x7f),
uint8_t((pointer / 128) & 0x7f)}; uint8_t((pointer / 128) & 0x7f));
_sendMessage(cmd, 3); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::songSelect(uint8_t song) { void MIDIEncoder<Sender>::songSelect(uint8_t song) {
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t(song & 0x7f)}; const auto cmd = MakeCommand(uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t(song & 0x7f));
_sendMessage(cmd, 2); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::tuneRequest() { void MIDIEncoder<Sender>::tuneRequest() {
uint8_t cmd = uint8_t(Status::TuneRequest); constexpr auto cmd = MakeCommand(uint8_t(Status::TuneRequest));
_sendMessage(&cmd, 1); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::startSeq() { void MIDIEncoder<Sender>::startSeq() {
uint8_t cmd = uint8_t(Status::Start); constexpr auto cmd = MakeCommand(uint8_t(Status::Start));
_sendMessage(&cmd, 1); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::continueSeq() { void MIDIEncoder<Sender>::continueSeq() {
uint8_t cmd = uint8_t(Status::Continue); constexpr auto cmd = MakeCommand(uint8_t(Status::Continue));
_sendMessage(&cmd, 1); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::stopSeq() { void MIDIEncoder<Sender>::stopSeq() {
uint8_t cmd = uint8_t(Status::Stop); constexpr auto cmd = MakeCommand(uint8_t(Status::Stop));
_sendMessage(&cmd, 1); _sendMessage(cmd);
} }
template <class Sender> template <class Sender>
void MIDIEncoder<Sender>::reset() { void MIDIEncoder<Sender>::reset() {
uint8_t cmd = uint8_t(Status::Reset); constexpr auto cmd = MakeCommand(uint8_t(Status::Reset));
_sendMessage(&cmd, 1); _sendMessage(cmd);
} }
template class MIDIEncoder<IMIDIOut>; template class MIDIEncoder<IMIDIOut>;

View File

@ -1,8 +1,9 @@
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include "logvisor/logvisor.hpp"
#include "boo/boo.hpp"
#include "LinuxMidi.hpp"
#include "boo/boo.hpp"
#include "lib/audiodev/LinuxMidi.hpp"
#include <logvisor/logvisor.hpp>
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
#include <unistd.h> #include <unistd.h>
@ -154,7 +155,7 @@ struct PulseAudioVoiceEngine : LinuxMidi {
m_mainloop = nullptr; m_mainloop = nullptr;
} }
~PulseAudioVoiceEngine() { ~PulseAudioVoiceEngine() override {
if (m_stream) { if (m_stream) {
pa_stream_disconnect(m_stream); pa_stream_disconnect(m_stream);
pa_stream_unref(m_stream); pa_stream_unref(m_stream);
@ -270,7 +271,7 @@ struct PulseAudioVoiceEngine : LinuxMidi {
if (i) if (i)
userdata->m_sinks.push_back(std::make_pair(i->name, i->description)); userdata->m_sinks.push_back(std::make_pair(i->name, i->description));
} }
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const { std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const override {
pa_operation* op = pa_context_get_sink_info_list(m_ctx, pa_sink_info_cb_t(_getSinkInfoListReply), (void*)this); pa_operation* op = pa_context_get_sink_info_list(m_ctx, pa_sink_info_cb_t(_getSinkInfoListReply), (void*)this);
_paIterate(op); _paIterate(op);
pa_operation_unref(op); pa_operation_unref(op);
@ -279,14 +280,14 @@ struct PulseAudioVoiceEngine : LinuxMidi {
return ret; return ret;
} }
std::string getCurrentAudioOutput() const { return m_sinkName; } std::string getCurrentAudioOutput() const override { return m_sinkName; }
bool m_sinkOk = false; bool m_sinkOk = false;
static void _checkAudioSinkReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata) { static void _checkAudioSinkReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata) {
if (i) if (i)
userdata->m_sinkOk = true; userdata->m_sinkOk = true;
} }
bool setCurrentAudioOutput(const char* name) { bool setCurrentAudioOutput(const char* name) override {
m_sinkOk = false; m_sinkOk = false;
pa_operation* op; pa_operation* op;
op = pa_context_get_sink_info_by_name(m_ctx, name, pa_sink_info_cb_t(_checkAudioSinkReply), this); op = pa_context_get_sink_info_by_name(m_ctx, name, pa_sink_info_cb_t(_checkAudioSinkReply), this);
@ -308,7 +309,7 @@ struct PulseAudioVoiceEngine : LinuxMidi {
} }
} }
void pumpAndMixVoices() { void pumpAndMixVoices() override {
if (!m_stream) { if (!m_stream) {
/* Dummy pump mode - use failsafe defaults for 1/60sec of samples */ /* Dummy pump mode - use failsafe defaults for 1/60sec of samples */
m_mixInfo.m_sampleRate = 32000.0; m_mixInfo.m_sampleRate = 32000.0;

View File

@ -1,23 +1,25 @@
#include "../win/Win32Common.hpp" #include "lib/win/Win32Common.hpp"
#include "AudioVoiceEngine.hpp"
#include "logvisor/logvisor.hpp" #include <iterator>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "lib/audiodev/AudioVoiceEngine.hpp"
#include <Mmdeviceapi.h> #include <Mmdeviceapi.h>
#include <Audioclient.h> #include <Audioclient.h>
#include <mmsystem.h> #include <mmsystem.h>
#include <Functiondiscoverykeys_devpkey.h> #include <Functiondiscoverykeys_devpkey.h>
#include <iterator> #include <logvisor/logvisor.hpp>
#ifdef TE_VIRTUAL_MIDI #ifdef TE_VIRTUAL_MIDI
#include <teVirtualMIDI.h> #include <teVirtualMIDI.h>
typedef LPVM_MIDI_PORT(CALLBACK* pfnvirtualMIDICreatePortEx2)(LPCWSTR portName, LPVM_MIDI_DATA_CB callback, using pfnvirtualMIDICreatePortEx2 = LPVM_MIDI_PORT(CALLBACK*)(LPCWSTR portName, LPVM_MIDI_DATA_CB callback,
DWORD_PTR dwCallbackInstance, DWORD maxSysexLength, DWORD_PTR dwCallbackInstance, DWORD maxSysexLength,
DWORD flags); DWORD flags);
typedef void(CALLBACK* pfnvirtualMIDIClosePort)(LPVM_MIDI_PORT midiPort); using pfnvirtualMIDIClosePort = void(CALLBACK*)(LPVM_MIDI_PORT midiPort);
typedef BOOL(CALLBACK* pfnvirtualMIDISendData)(LPVM_MIDI_PORT midiPort, LPBYTE midiDataBytes, DWORD length); using pfnvirtualMIDISendData = BOOL(CALLBACK*)(LPVM_MIDI_PORT midiPort, LPBYTE midiDataBytes, DWORD length);
typedef LPCWSTR(CALLBACK* pfnvirtualMIDIGetDriverVersion)(PWORD major, PWORD minor, PWORD release, PWORD build); using pfnvirtualMIDIGetDriverVersion = LPCWSTR(CALLBACK*)(PWORD major, PWORD minor, PWORD release, PWORD build);
static pfnvirtualMIDICreatePortEx2 virtualMIDICreatePortEx2PROC = nullptr; static pfnvirtualMIDICreatePortEx2 virtualMIDICreatePortEx2PROC = nullptr;
static pfnvirtualMIDIClosePort virtualMIDIClosePortPROC = nullptr; static pfnvirtualMIDIClosePort virtualMIDIClosePortPROC = nullptr;
static pfnvirtualMIDISendData virtualMIDISendDataPROC = nullptr; static pfnvirtualMIDISendData virtualMIDISendDataPROC = nullptr;
@ -38,9 +40,9 @@ namespace boo {
static logvisor::Module Log("boo::WASAPI"); static logvisor::Module Log("boo::WASAPI");
#define SAFE_RELEASE(punk) \ #define SAFE_RELEASE(punk) \
if ((punk) != NULL) { \ if ((punk) != nullptr) { \
(punk)->Release(); \ (punk)->Release(); \
(punk) = NULL; \ (punk) = nullptr; \
} }
struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine { struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
@ -70,11 +72,11 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
// IUnknown methods -- AddRef, Release, and QueryInterface // IUnknown methods -- AddRef, Release, and QueryInterface
ULONG STDMETHODCALLTYPE AddRef() { ULONG STDMETHODCALLTYPE AddRef() override {
return InterlockedIncrement(&_cRef); return InterlockedIncrement(&_cRef);
} }
ULONG STDMETHODCALLTYPE Release() { ULONG STDMETHODCALLTYPE Release() override {
ULONG ulRef = InterlockedDecrement(&_cRef); ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef) { if (0 == ulRef) {
delete this; delete this;
@ -82,7 +84,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
return ulRef; return ulRef;
} }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface) { HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface) override {
if (IID_IUnknown == riid) { if (IID_IUnknown == riid) {
AddRef(); AddRef();
*ppvInterface = (IUnknown*)this; *ppvInterface = (IUnknown*)this;
@ -90,7 +92,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
AddRef(); AddRef();
*ppvInterface = (IMMNotificationClient*)this; *ppvInterface = (IMMNotificationClient*)this;
} else { } else {
*ppvInterface = NULL; *ppvInterface = nullptr;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
return S_OK; return S_OK;
@ -98,18 +100,20 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
// Callback methods for device-event notifications. // Callback methods for device-event notifications.
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) { HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) override {
m_parent.m_rebuild = true; m_parent.m_rebuild = true;
return S_OK; return S_OK;
} }
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) { return S_OK; } HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) override { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) { return S_OK; } HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) override { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { return S_OK; } HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override { return S_OK; }
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { return S_OK; } HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) override {
return S_OK;
}
} m_notificationClient; } m_notificationClient;
#endif #endif
@ -117,7 +121,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
#if !WINDOWS_STORE #if !WINDOWS_STORE
if (!m_device) { if (!m_device) {
if (FAILED(m_enumerator->GetDevice(MBSTWCS(m_sinkName.c_str()).c_str(), &m_device))) { if (FAILED(m_enumerator->GetDevice(MBSTWCS(m_sinkName.c_str()).c_str(), &m_device))) {
Log.report(logvisor::Error, fmt("unable to obtain audio device %s"), m_sinkName); Log.report(logvisor::Error, fmt("unable to obtain audio device {}"), m_sinkName);
m_device.Reset(); m_device.Reset();
return; return;
} }
@ -200,7 +204,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
chMapOut.m_channels[7] = AudioChannel::SideRight; chMapOut.m_channels[7] = AudioChannel::SideRight;
break; break;
default: default:
Log.report(logvisor::Warning, fmt("unknown channel layout %u; using stereo"), pwfx->Format.nChannels); Log.report(logvisor::Warning, fmt("unknown channel layout {}; using stereo"), pwfx->Format.nChannels);
chMapOut.m_channelCount = 2; chMapOut.m_channelCount = 2;
chMapOut.m_channels[0] = AudioChannel::FrontLeft; chMapOut.m_channels[0] = AudioChannel::FrontLeft;
chMapOut.m_channels[1] = AudioChannel::FrontRight; chMapOut.m_channels[1] = AudioChannel::FrontRight;
@ -301,7 +305,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
AddRef(); AddRef();
*ppvInterface = (IActivateAudioInterfaceCompletionHandler*)this; *ppvInterface = (IActivateAudioInterfaceCompletionHandler*)this;
} else { } else {
*ppvInterface = NULL; *ppvInterface = nullptr;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
return S_OK; return S_OK;
@ -386,7 +390,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
_resetSampleRate(); _resetSampleRate();
} }
void pumpAndMixVoices() { void pumpAndMixVoices() override {
#if WINDOWS_STORE #if WINDOWS_STORE
if (!m_ready) if (!m_ready)
return; return;
@ -463,9 +467,9 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
} }
} }
std::string getCurrentAudioOutput() const { return m_sinkName; } std::string getCurrentAudioOutput() const override { return m_sinkName; }
bool setCurrentAudioOutput(const char* name) { bool setCurrentAudioOutput(const char* name) override {
ComPtr<IMMDevice> newDevice; ComPtr<IMMDevice> newDevice;
if (FAILED(m_enumerator->GetDevice(MBSTWCS(name).c_str(), &newDevice))) { if (FAILED(m_enumerator->GetDevice(MBSTWCS(name).c_str(), &newDevice))) {
Log.report(logvisor::Error, fmt("unable to obtain audio device {}"), name); Log.report(logvisor::Error, fmt("unable to obtain audio device {}"), name);
@ -477,7 +481,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
return true; return true;
} }
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const { std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const override {
std::vector<std::pair<std::string, std::string>> ret; std::vector<std::pair<std::string, std::string>> ret;
ComPtr<IMMDeviceCollection> collection; ComPtr<IMMDeviceCollection> collection;
@ -507,7 +511,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
} }
#if !WINDOWS_STORE #if !WINDOWS_STORE
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const { std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const override {
std::vector<std::pair<std::string, std::string>> ret; std::vector<std::pair<std::string, std::string>> ret;
UINT numInDevices = midiInGetNumDevs(); UINT numInDevices = midiInGetNumDevs();
@ -547,7 +551,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
bool supportsVirtualMIDIIn() const { bool supportsVirtualMIDIIn() const override {
#ifdef TE_VIRTUAL_MIDI #ifdef TE_VIRTUAL_MIDI
WORD major, minor, release, build; WORD major, minor, release, build;
return virtualMIDIGetDriverVersionPROC && return virtualMIDIGetDriverVersionPROC &&
@ -588,9 +592,9 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
VMIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver) : IMIDIIn(parent, true, std::move(receiver)) {} VMIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver) : IMIDIIn(parent, true, std::move(receiver)) {}
~VMIDIIn() { virtualMIDIClosePortPROC(m_midi); } ~VMIDIIn() override { virtualMIDIClosePortPROC(m_midi); }
std::string description() const { return "Virtual MIDI-In"; } std::string description() const override { return "Virtual MIDI-In"; }
}; };
struct VMIDIOut : public IMIDIOut { struct VMIDIOut : public IMIDIOut {
@ -598,11 +602,11 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
VMIDIOut(WASAPIAudioVoiceEngine* parent) : IMIDIOut(parent, true) {} VMIDIOut(WASAPIAudioVoiceEngine* parent) : IMIDIOut(parent, true) {}
~VMIDIOut() { virtualMIDIClosePortPROC(m_midi); } ~VMIDIOut() override { virtualMIDIClosePortPROC(m_midi); }
std::string description() const { return "Virtual MIDI-Out"; } std::string description() const override { return "Virtual MIDI-Out"; }
size_t send(const void* buf, size_t len) const { size_t send(const void* buf, size_t len) const override {
return virtualMIDISendDataPROC(m_midi, (LPBYTE)buf, len) ? len : 0; return virtualMIDISendDataPROC(m_midi, (LPBYTE)buf, len) ? len : 0;
} }
}; };
@ -613,11 +617,11 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
VMIDIInOut(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver) VMIDIInOut(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver)
: IMIDIInOut(parent, true, std::move(receiver)) {} : IMIDIInOut(parent, true, std::move(receiver)) {}
~VMIDIInOut() { virtualMIDIClosePortPROC(m_midi); } ~VMIDIInOut() override { virtualMIDIClosePortPROC(m_midi); }
std::string description() const { return "Virtual MIDI-In/Out"; } std::string description() const override { return "Virtual MIDI-In/Out"; }
size_t send(const void* buf, size_t len) const { size_t send(const void* buf, size_t len) const override {
return virtualMIDISendDataPROC(m_midi, (LPBYTE)buf, len) ? len : 0; return virtualMIDISendDataPROC(m_midi, (LPBYTE)buf, len) ? len : 0;
} }
}; };
@ -628,9 +632,9 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
MIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver) : IMIDIIn(parent, false, std::move(receiver)) {} MIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver) : IMIDIIn(parent, false, std::move(receiver)) {}
~MIDIIn() { midiInClose(m_midi); } ~MIDIIn() override { midiInClose(m_midi); }
std::string description() const { std::string description() const override {
UINT id = 0; UINT id = 0;
midiInGetID(m_midi, &id); midiInGetID(m_midi, &id);
MIDIINCAPS caps; MIDIINCAPS caps;
@ -661,16 +665,16 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
m_hdr.dwBufferLength = 512; m_hdr.dwBufferLength = 512;
m_hdr.dwFlags = MHDR_ISSTRM; m_hdr.dwFlags = MHDR_ISSTRM;
midiOutPrepareHeader(m_midi, &m_hdr, sizeof(m_hdr)); midiOutPrepareHeader(m_midi, &m_hdr, sizeof(m_hdr));
midiStreamOpen(&m_strm, &id, 1, NULL, NULL, CALLBACK_NULL); midiStreamOpen(&m_strm, &id, 1, 0, 0, CALLBACK_NULL);
} }
~MIDIOut() { ~MIDIOut() override {
midiStreamClose(m_strm); midiStreamClose(m_strm);
midiOutUnprepareHeader(m_midi, &m_hdr, sizeof(m_hdr)); midiOutUnprepareHeader(m_midi, &m_hdr, sizeof(m_hdr));
midiOutClose(m_midi); midiOutClose(m_midi);
} }
std::string description() const { std::string description() const override {
UINT id = 0; UINT id = 0;
midiOutGetID(m_midi, &id); midiOutGetID(m_midi, &id);
MIDIOUTCAPS caps; MIDIOUTCAPS caps;
@ -684,7 +688,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
#endif #endif
} }
size_t send(const void* buf, size_t len) const { size_t send(const void* buf, size_t len) const override {
memcpy(const_cast<MIDIOut*>(this)->m_buf, buf, std::min(len, size_t(512))); memcpy(const_cast<MIDIOut*>(this)->m_buf, buf, std::min(len, size_t(512)));
const_cast<MIDIOut*>(this)->m_hdr.dwBytesRecorded = len; const_cast<MIDIOut*>(this)->m_hdr.dwBytesRecorded = len;
midiStreamOut(m_strm, LPMIDIHDR(&m_hdr), sizeof(m_hdr)); midiStreamOut(m_strm, LPMIDIHDR(&m_hdr), sizeof(m_hdr));
@ -710,17 +714,17 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
m_hdr.dwBufferLength = 512; m_hdr.dwBufferLength = 512;
m_hdr.dwFlags = MHDR_ISSTRM; m_hdr.dwFlags = MHDR_ISSTRM;
midiOutPrepareHeader(m_midiOut, &m_hdr, sizeof(m_hdr)); midiOutPrepareHeader(m_midiOut, &m_hdr, sizeof(m_hdr));
midiStreamOpen(&m_strm, &id, 1, NULL, NULL, CALLBACK_NULL); midiStreamOpen(&m_strm, &id, 1, 0, 0, CALLBACK_NULL);
} }
~MIDIInOut() { ~MIDIInOut() override {
midiInClose(m_midiIn); midiInClose(m_midiIn);
midiStreamClose(m_strm); midiStreamClose(m_strm);
midiOutUnprepareHeader(m_midiOut, &m_hdr, sizeof(m_hdr)); midiOutUnprepareHeader(m_midiOut, &m_hdr, sizeof(m_hdr));
midiOutClose(m_midiOut); midiOutClose(m_midiOut);
} }
std::string description() const { std::string description() const override {
UINT id = 0; UINT id = 0;
midiOutGetID(m_midiOut, &id); midiOutGetID(m_midiOut, &id);
MIDIOUTCAPS caps; MIDIOUTCAPS caps;
@ -734,7 +738,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
#endif #endif
} }
size_t send(const void* buf, size_t len) const { size_t send(const void* buf, size_t len) const override {
memcpy(const_cast<uint8_t*>(m_buf), buf, std::min(len, size_t(512))); memcpy(const_cast<uint8_t*>(m_buf), buf, std::min(len, size_t(512)));
const_cast<MIDIHDR&>(m_hdr).dwBytesRecorded = len; const_cast<MIDIHDR&>(m_hdr).dwBytesRecorded = len;
midiStreamOut(m_strm, LPMIDIHDR(&m_hdr), sizeof(m_hdr)); midiStreamOut(m_strm, LPMIDIHDR(&m_hdr), sizeof(m_hdr));
@ -742,7 +746,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
} }
}; };
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) override {
#ifdef TE_VIRTUAL_MIDI #ifdef TE_VIRTUAL_MIDI
if (!virtualMIDICreatePortEx2PROC) if (!virtualMIDICreatePortEx2PROC)
return {}; return {};
@ -764,7 +768,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
#endif #endif
} }
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() { std::unique_ptr<IMIDIOut> newVirtualMIDIOut() override {
#ifdef TE_VIRTUAL_MIDI #ifdef TE_VIRTUAL_MIDI
if (!virtualMIDICreatePortEx2PROC) if (!virtualMIDICreatePortEx2PROC)
return {}; return {};
@ -785,7 +789,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
#endif #endif
} }
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) override {
#ifdef TE_VIRTUAL_MIDI #ifdef TE_VIRTUAL_MIDI
if (!virtualMIDICreatePortEx2PROC) if (!virtualMIDICreatePortEx2PROC)
return {}; return {};
@ -807,7 +811,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
#endif #endif
} }
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) override {
if (strncmp(name, "in", 2)) if (strncmp(name, "in", 2))
return {}; return {};
long id = strtol(name + 2, nullptr, 10); long id = strtol(name + 2, nullptr, 10);
@ -824,7 +828,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
return ret; return ret;
} }
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) { std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) override {
if (strncmp(name, "out", 3)) if (strncmp(name, "out", 3))
return {}; return {};
long id = strtol(name + 3, nullptr, 10); long id = strtol(name + 3, nullptr, 10);
@ -833,14 +837,14 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
if (!ret) if (!ret)
return {}; return {};
if (FAILED(midiOutOpen(&static_cast<MIDIOut&>(*ret).m_midi, id, NULL, NULL, CALLBACK_NULL))) if (FAILED(midiOutOpen(&static_cast<MIDIOut&>(*ret).m_midi, id, 0, 0, CALLBACK_NULL)))
return {}; return {};
static_cast<MIDIOut&>(*ret).prepare(); static_cast<MIDIOut&>(*ret).prepare();
return ret; return ret;
} }
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) override {
const char* in = strstr(name, "in"); const char* in = strstr(name, "in");
const char* out = strstr(name, "out"); const char* out = strstr(name, "out");
@ -859,28 +863,28 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
return {}; return {};
midiInStart(static_cast<MIDIInOut&>(*ret).m_midiIn); midiInStart(static_cast<MIDIInOut&>(*ret).m_midiIn);
if (FAILED(midiOutOpen(&static_cast<MIDIInOut&>(*ret).m_midiOut, outId, NULL, NULL, CALLBACK_NULL))) if (FAILED(midiOutOpen(&static_cast<MIDIInOut&>(*ret).m_midiOut, outId, 0, 0, CALLBACK_NULL)))
return {}; return {};
static_cast<MIDIInOut&>(*ret).prepare(); static_cast<MIDIInOut&>(*ret).prepare();
return ret; return ret;
} }
bool useMIDILock() const { return true; } bool useMIDILock() const override { return true; }
#else #else
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const { return {}; } std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const override { return {}; }
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) { return {}; } std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) override { return {}; }
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() { return {}; } std::unique_ptr<IMIDIOut> newVirtualMIDIOut() override { return {}; }
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) { return {}; } std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) override { return {}; }
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) { return {}; } std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) override { return {}; }
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) { return {}; } std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) override { return {}; }
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) { return {}; } std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) override { return {}; }
bool useMIDILock() const { return false; } bool useMIDILock() const { return false; }
#endif #endif

View File

@ -1,6 +1,9 @@
#include "AudioVoiceEngine.hpp" #include "lib/audiodev/AudioVoiceEngine.hpp"
#include "logvisor/logvisor.hpp"
#include <cstdio>
#include "boo/audiodev/IAudioVoiceEngine.hpp" #include "boo/audiodev/IAudioVoiceEngine.hpp"
#include <logvisor/logvisor.hpp>
namespace boo { namespace boo {
@ -11,15 +14,17 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine {
AudioChannelSet _getAvailableSet() { return AudioChannelSet::Stereo; } AudioChannelSet _getAvailableSet() { return AudioChannelSet::Stereo; }
std::string getCurrentAudioOutput() const { return "wavout"; } std::string getCurrentAudioOutput() const override { return "wavout"; }
bool setCurrentAudioOutput(const char* name) { return false; } bool setCurrentAudioOutput(const char* name) override { return false; }
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const { return {{"wavout", "WAVOut"}}; } std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const override {
return {{"wavout", "WAVOut"}};
}
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const { return {}; } std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const override { return {}; }
bool supportsVirtualMIDIIn() const { return false; } bool supportsVirtualMIDIIn() const override { return false; }
ReceiveFunctor* m_midiReceiver = nullptr; ReceiveFunctor* m_midiReceiver = nullptr;
@ -27,26 +32,26 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine {
MIDIIn(WAVOutVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver) MIDIIn(WAVOutVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIIn(parent, virt, std::move(receiver)) {} : IMIDIIn(parent, virt, std::move(receiver)) {}
std::string description() const { return "WAVOut MIDI"; } std::string description() const override { return "WAVOut MIDI"; }
}; };
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) { std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) override {
std::unique_ptr<IMIDIIn> ret = std::make_unique<MIDIIn>(nullptr, true, std::move(receiver)); std::unique_ptr<IMIDIIn> ret = std::make_unique<MIDIIn>(nullptr, true, std::move(receiver));
m_midiReceiver = &ret->m_receiver; m_midiReceiver = &ret->m_receiver;
return ret; return ret;
} }
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() { return {}; } std::unique_ptr<IMIDIOut> newVirtualMIDIOut() override { return {}; }
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) { return {}; } std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) override { return {}; }
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) { return {}; } std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) override { return {}; }
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) { return {}; } std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) override { return {}; }
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) { return {}; } std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) override { return {}; }
bool useMIDILock() const { return false; } bool useMIDILock() const override { return false; }
FILE* m_fp = nullptr; FILE* m_fp = nullptr;
size_t m_bytesWritten = 0; size_t m_bytesWritten = 0;
@ -207,7 +212,7 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine {
fclose(m_fp); fclose(m_fp);
} }
~WAVOutVoiceEngine() { finishWav(); } ~WAVOutVoiceEngine() override { finishWav(); }
void _buildAudioRenderClient() { void _buildAudioRenderClient() {
m_5msFrames = m_mixInfo.m_sampleRate * 5 / 1000; m_5msFrames = m_mixInfo.m_sampleRate * 5 / 1000;
@ -221,7 +226,7 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine {
_resetSampleRate(); _resetSampleRate();
} }
void pumpAndMixVoices() { void pumpAndMixVoices() override {
size_t frameSz = 4 * m_mixInfo.m_channelMap.m_channelCount; size_t frameSz = 4 * m_mixInfo.m_channelMap.m_channelCount;
_pumpAndMixVoices(m_5msFrames, m_interleavedBuf.data()); _pumpAndMixVoices(m_5msFrames, m_interleavedBuf.data());
fwrite(m_interleavedBuf.data(), 1, m_5msFrames * frameSz, m_fp); fwrite(m_interleavedBuf.data(), 1, m_5msFrames * frameSz, m_fp);

View File

@ -3,17 +3,18 @@
/* Private header for managing shader data /* Private header for managing shader data
* binding lifetimes through rendering cycle */ * binding lifetimes through rendering cycle */
#include <array>
#include <atomic> #include <atomic>
#include <vector>
#include <mutex>
#include <cassert> #include <cassert>
#include <thread>
#include <mutex>
#include <condition_variable> #include <condition_variable>
#include <mutex>
#include <queue> #include <queue>
#include <thread>
#include <vector>
#include "boo/graphicsdev/IGraphicsDataFactory.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "boo/graphicsdev/IGraphicsCommandQueue.hpp" #include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
#include "../Common.hpp" #include "lib/Common.hpp"
namespace boo { namespace boo {
@ -63,9 +64,6 @@ struct BaseGraphicsData : ListNode<BaseGraphicsData, GraphicsDataFactoryHead*> {
auto* head = getHead<T>(); auto* head = getHead<T>();
return head ? head->countForward() : 0; return head ? head->countForward() : 0;
} }
std::unique_lock<std::recursive_mutex> destructorLock() override {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
explicit BaseGraphicsData(GraphicsDataFactoryHead& head __BooTraceArgs) explicit BaseGraphicsData(GraphicsDataFactoryHead& head __BooTraceArgs)
: ListNode<BaseGraphicsData, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer {} : ListNode<BaseGraphicsData, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer {}
@ -131,9 +129,6 @@ struct BaseGraphicsPool : ListNode<BaseGraphicsPool, GraphicsDataFactoryHead*> {
auto* head = getHead<T>(); auto* head = getHead<T>();
return head ? head->countForward() : 0; return head ? head->countForward() : 0;
} }
std::unique_lock<std::recursive_mutex> destructorLock() override {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
explicit BaseGraphicsPool(GraphicsDataFactoryHead& head __BooTraceArgs) explicit BaseGraphicsPool(GraphicsDataFactoryHead& head __BooTraceArgs)
: ListNode<BaseGraphicsPool, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer {} : ListNode<BaseGraphicsPool, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer {}
@ -158,10 +153,6 @@ struct GraphicsDataNode : ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<
return std::unique_lock<std::recursive_mutex>{head->m_head->m_dataMutex}; return std::unique_lock<std::recursive_mutex>{head->m_head->m_dataMutex};
} }
std::unique_lock<std::recursive_mutex> destructorLock() override {
return std::unique_lock<std::recursive_mutex>{base::m_head->m_head->m_dataMutex};
}
explicit GraphicsDataNode(const ObjToken<DataCls>& data) explicit GraphicsDataNode(const ObjToken<DataCls>& data)
: ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<DataCls>, NodeCls>(data) {} : ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<DataCls>, NodeCls>(data) {}
@ -249,7 +240,7 @@ public:
m_backcv.wait(lk, [this]() { return m_outstandingTasks == 0 || !m_running; }); m_backcv.wait(lk, [this]() { return m_outstandingTasks == 0 || !m_running; });
} }
bool isReady() { bool isReady() const {
return m_outstandingTasks == 0 || !m_running; return m_outstandingTasks == 0 || !m_running;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#include "boo/graphicsdev/glxew.h" #include "boo/graphicsdev/glxew.h"
#include "logvisor/logvisor.hpp" #include <logvisor/logvisor.hpp>
namespace boo { namespace boo {
static logvisor::Module Log("boo::GLX"); static logvisor::Module Log("boo::GLX");

View File

@ -1,16 +1,17 @@
#include "../mac/CocoaCommon.hpp" #include "lib/mac/CocoaCommon.hpp"
#if BOO_HAS_METAL #if BOO_HAS_METAL
#include "logvisor/logvisor.hpp"
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/graphicsdev/Metal.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include "Common.hpp" #include "boo/graphicsdev/Metal.hpp"
#include <vector> #include "lib/graphicsdev/Common.hpp"
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include "xxhash/xxhash.h" #include <vector>
#include <logvisor/logvisor.hpp>
#if !__has_feature(objc_arc) #if !__has_feature(objc_arc)
#error ARC Required #error ARC Required
@ -848,11 +849,13 @@ class MetalShaderStage : public GraphicsDataNode<IShaderStage> {
shaderLib = [ctx->m_dev newLibraryWithSource:@((const char*) (data + 1)) shaderLib = [ctx->m_dev newLibraryWithSource:@((const char*) (data + 1))
options:compOpts options:compOpts
error:&err]; error:&err];
if (!shaderLib) if (!shaderLib) {
fmt::print(fmt("{}\n"), data + 1); fmt::print(fmt("{}\n"), data + 1);
}
}
if (!shaderLib) {
Log.report(logvisor::Fatal, fmt("error creating library: {}"), [[err localizedDescription] UTF8String]);
} }
if (!shaderLib)
Log.report(logvisor::Fatal, fmt("error creating library: %s"), [[err localizedDescription] UTF8String]);
NSString* funcName; NSString* funcName;
switch (stage) { switch (stage) {
@ -969,9 +972,10 @@ protected:
desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
NSError* err = nullptr; NSError* err = nullptr;
m_state = [ctx->m_dev newRenderPipelineStateWithDescriptor:desc error:&err]; m_state = [ctx->m_dev newRenderPipelineStateWithDescriptor:desc error:&err];
if (err) if (err) {
Log.report(logvisor::Fatal, fmt("error making shader pipeline: %s"), Log.report(logvisor::Fatal, fmt("error making shader pipeline: {}"),
[[err localizedDescription] UTF8String]); [[err localizedDescription] UTF8String]);
}
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new]; MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
switch (info.depthTest) { switch (info.depthTest) {
@ -1043,9 +1047,10 @@ class MetalTessellationShaderPipeline : public MetalShaderPipeline {
NSError* err = nullptr; NSError* err = nullptr;
m_computeState = [ctx->m_dev newComputePipelineStateWithDescriptor:compDesc options:MTLPipelineOptionNone m_computeState = [ctx->m_dev newComputePipelineStateWithDescriptor:compDesc options:MTLPipelineOptionNone
reflection:nil error:&err]; reflection:nil error:&err];
if (err) if (err) {
Log.report(logvisor::Fatal, fmt("error making compute pipeline: %s"), Log.report(logvisor::Fatal, fmt("error making compute pipeline: {}"),
[[err localizedDescription] UTF8String]); [[err localizedDescription] UTF8String]);
}
} }
void draw(MetalCommandQueue& q, size_t start, size_t count); void draw(MetalCommandQueue& q, size_t start, size_t count);
@ -1147,9 +1152,10 @@ struct MetalShaderDataBinding : GraphicsDataNode<IShaderDataBinding> {
m_ubufOffs.reserve(ubufCount); m_ubufOffs.reserve(ubufCount);
for (size_t i = 0; i < ubufCount; ++i) { for (size_t i = 0; i < ubufCount; ++i) {
#ifndef NDEBUG #ifndef NDEBUG
if (ubufOffs[i] % 256) if (ubufOffs[i] % 256) {
Log.report(logvisor::Fatal, fmt("non-256-byte-aligned uniform-offset %d provided to newShaderDataBinding"), Log.report(logvisor::Fatal, fmt("non-256-byte-aligned uniform-offset {} provided to newShaderDataBinding"),
int(i)); i);
}
#endif #endif
m_ubufOffs.push_back(ubufOffs[i]); m_ubufOffs.push_back(ubufOffs[i]);
} }
@ -1157,8 +1163,9 @@ struct MetalShaderDataBinding : GraphicsDataNode<IShaderDataBinding> {
m_ubufs.reserve(ubufCount); m_ubufs.reserve(ubufCount);
for (size_t i = 0; i < ubufCount; ++i) { for (size_t i = 0; i < ubufCount; ++i) {
#ifndef NDEBUG #ifndef NDEBUG
if (!ubufs[i]) if (!ubufs[i]) {
Log.report(logvisor::Fatal, fmt("null uniform-buffer %d provided to newShaderDataBinding"), int(i)); Log.report(logvisor::Fatal, fmt("null uniform-buffer {} provided to newShaderDataBinding"), i);
}
#endif #endif
m_ubufs.push_back(ubufs[i]); m_ubufs.push_back(ubufs[i]);
} }
@ -2005,7 +2012,6 @@ void MetalDataFactoryImpl::SetupGammaResources() {
ObjToken<ITexture> texs[] = {{}, m_gammaLUT.get()}; ObjToken<ITexture> texs[] = {{}, m_gammaLUT.get()};
m_gammaBinding = ctx.newShaderDataBinding(m_gammaShader, m_gammaVBO.get(), {}, {}, m_gammaBinding = ctx.newShaderDataBinding(m_gammaShader, m_gammaVBO.get(), {}, {},
0, nullptr, nullptr, 2, texs, nullptr, nullptr); 0, nullptr, nullptr, 2, texs, nullptr, nullptr);
return true; return true;
} BooTrace); } BooTrace);
} }

View File

@ -1,15 +1,18 @@
#include "boo/graphicsdev/Vulkan.hpp" #include "boo/graphicsdev/Vulkan.hpp"
#include "boo/IGraphicsContext.hpp"
#include <vector>
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <vector>
#include <glslang/Public/ShaderLang.h> #include <glslang/Public/ShaderLang.h>
#include <StandAlone/ResourceLimits.h> #include <StandAlone/ResourceLimits.h>
#include <SPIRV/GlslangToSpv.h> #include <SPIRV/GlslangToSpv.h>
#include <SPIRV/disassemble.h> #include <SPIRV/disassemble.h>
#include "boo/IGraphicsContext.hpp"
#include "boo/graphicsdev/GLSLMacros.hpp" #include "boo/graphicsdev/GLSLMacros.hpp"
#include "Common.hpp" #include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
#include "xxhash/xxhash.h" #include "lib/graphicsdev/Common.hpp"
#define AMD_PAL_HACK 1 #define AMD_PAL_HACK 1
@ -17,7 +20,7 @@
#define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_STATIC_VULKAN_FUNCTIONS 0
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#include "logvisor/logvisor.hpp" #include <logvisor/logvisor.hpp>
#define BOO_VK_MAX_DESCRIPTOR_SETS 65536 #define BOO_VK_MAX_DESCRIPTOR_SETS 65536
@ -188,7 +191,7 @@ static void SetImageLayout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlag
uint32_t layerCount, uint32_t baseMipLevel = 0) { uint32_t layerCount, uint32_t baseMipLevel = 0) {
VkImageMemoryBarrier imageMemoryBarrier = {}; VkImageMemoryBarrier imageMemoryBarrier = {};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier.pNext = NULL; imageMemoryBarrier.pNext = nullptr;
imageMemoryBarrier.srcAccessMask = 0; imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = 0; imageMemoryBarrier.dstAccessMask = 0;
imageMemoryBarrier.oldLayout = old_image_layout; imageMemoryBarrier.oldLayout = old_image_layout;
@ -261,7 +264,7 @@ static void SetImageLayout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlag
break; break;
} }
vk::CmdPipelineBarrier(cmd, src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier); vk::CmdPipelineBarrier(cmd, src_stages, dest_stages, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
} }
static VkResult InitGlobalExtensionProperties(VulkanContext::LayerProperties& layerProps) { static VkResult InitGlobalExtensionProperties(VulkanContext::LayerProperties& layerProps) {
@ -1060,9 +1063,6 @@ struct VulkanDescriptorPool : ListNode<VulkanDescriptorPool, VulkanDataFactoryIm
~VulkanDescriptorPool() { vk::DestroyDescriptorPool(m_head->m_ctx->m_dev, m_descPool, nullptr); } ~VulkanDescriptorPool() { vk::DestroyDescriptorPool(m_head->m_ctx->m_dev, m_descPool, nullptr); }
std::unique_lock<std::recursive_mutex> destructorLock() override {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
static std::unique_lock<std::recursive_mutex> _getHeadLock(VulkanDataFactoryImpl* factory) { static std::unique_lock<std::recursive_mutex> _getHeadLock(VulkanDataFactoryImpl* factory) {
return std::unique_lock<std::recursive_mutex>{factory->m_dataMutex}; return std::unique_lock<std::recursive_mutex>{factory->m_dataMutex};
} }
@ -2668,9 +2668,10 @@ struct VulkanShaderDataBinding : GraphicsDataNode<IShaderDataBinding> {
m_ubufOffs.reserve(ubufCount); m_ubufOffs.reserve(ubufCount);
for (size_t i = 0; i < ubufCount; ++i) { for (size_t i = 0; i < ubufCount; ++i) {
#ifndef NDEBUG #ifndef NDEBUG
if (ubufOffs[i] % 256) if (ubufOffs[i] % 256) {
Log.report(logvisor::Fatal, fmt("non-256-byte-aligned uniform-offset {} provided to newShaderDataBinding"), Log.report(logvisor::Fatal, fmt("non-256-byte-aligned uniform-offset {} provided to newShaderDataBinding"),
int(i)); i);
}
#endif #endif
std::array<VkDescriptorBufferInfo, 2> fillArr; std::array<VkDescriptorBufferInfo, 2> fillArr;
fillArr.fill({VK_NULL_HANDLE, ubufOffs[i], (ubufSizes[i] + 255) & ~255}); fillArr.fill({VK_NULL_HANDLE, ubufOffs[i], (ubufSizes[i] + 255) & ~255});
@ -2680,8 +2681,9 @@ struct VulkanShaderDataBinding : GraphicsDataNode<IShaderDataBinding> {
m_ubufs.reserve(ubufCount); m_ubufs.reserve(ubufCount);
for (size_t i = 0; i < ubufCount; ++i) { for (size_t i = 0; i < ubufCount; ++i) {
#ifndef NDEBUG #ifndef NDEBUG
if (!ubufs[i]) if (!ubufs[i]) {
Log.report(logvisor::Fatal, fmt("null uniform-buffer {} provided to newShaderDataBinding"), int(i)); Log.report(logvisor::Fatal, fmt("null uniform-buffer {} provided to newShaderDataBinding"), i);
}
#endif #endif
m_ubufs.push_back(ubufs[i]); m_ubufs.push_back(ubufs[i]);
} }

View File

@ -1,9 +1,13 @@
#include "logvisor/logvisor.hpp"
#include "boo/graphicsdev/NX.hpp" #include "boo/graphicsdev/NX.hpp"
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include "boo/graphicsdev/GLSLMacros.hpp" #include "boo/graphicsdev/GLSLMacros.hpp"
#include "../Common.hpp" #include "lib/graphicsdev/Common.hpp"
#include "xxhash/xxhash.h"
#include "main/shaderobj.h" #include "main/shaderobj.h"
#include "st_program.h" #include "st_program.h"
@ -19,6 +23,9 @@ extern "C" {
#include "gallium/winsys/nouveau/switch/nouveau_switch_public.h" #include "gallium/winsys/nouveau/switch/nouveau_switch_public.h"
} }
#include <logvisor/logvisor.hpp>
#include <xxhash/xxhash.h>
#include <switch.h> #include <switch.h>
namespace boo { namespace boo {
@ -1801,7 +1808,7 @@ bool NXContext::initialize() {
gfxInitDefault(); gfxInitDefault();
gfxSetMode(GfxMode_TiledDouble); gfxSetMode(GfxMode_TiledDouble);
consoleInit(NULL); consoleInit(nullptr);
printf("Activated console\n\n"); printf("Activated console\n\n");
m_screen = nouveau_switch_screen_create(); m_screen = nouveau_switch_screen_create();
if (!m_screen) { if (!m_screen) {

View File

@ -1,7 +1,6 @@
#include "boo/inputdev/DeviceBase.hpp" #include "boo/inputdev/DeviceBase.hpp"
#include "boo/inputdev/DeviceToken.hpp" #include "boo/inputdev/DeviceToken.hpp"
#include "IHIDDevice.hpp" #include "lib/inputdev/IHIDDevice.hpp"
#include <cstdarg>
namespace boo { namespace boo {
@ -37,25 +36,25 @@ size_t DeviceBase::receiveUSBInterruptTransfer(uint8_t* data, size_t length) {
return false; return false;
} }
unsigned DeviceBase::getVendorId() { unsigned DeviceBase::getVendorId() const {
if (m_token) if (m_token)
return m_token->getVendorId(); return m_token->getVendorId();
return -1; return -1;
} }
unsigned DeviceBase::getProductId() { unsigned DeviceBase::getProductId() const {
if (m_token) if (m_token)
return m_token->getProductId(); return m_token->getProductId();
return -1; return -1;
} }
std::string_view DeviceBase::getVendorName() { std::string_view DeviceBase::getVendorName() const {
if (m_token) if (m_token)
return m_token->getVendorName(); return m_token->getVendorName();
return {}; return {};
} }
std::string_view DeviceBase::getProductName() { std::string_view DeviceBase::getProductName() const {
if (m_token) if (m_token)
return m_token->getProductName(); return m_token->getProductName();
return {}; return {};
@ -63,14 +62,14 @@ std::string_view DeviceBase::getProductName() {
#if _WIN32 #if _WIN32
#if !WINDOWS_STORE #if !WINDOWS_STORE
const PHIDP_PREPARSED_DATA DeviceBase::getReportDescriptor() { PHIDP_PREPARSED_DATA DeviceBase::getReportDescriptor() const {
if (m_hidDev) if (m_hidDev)
return m_hidDev->_getReportDescriptor(); return m_hidDev->_getReportDescriptor();
return {}; return {};
} }
#endif #endif
#else #else
std::vector<uint8_t> DeviceBase::getReportDescriptor() { std::vector<uint8_t> DeviceBase::getReportDescriptor() const {
if (m_hidDev) if (m_hidDev)
return m_hidDev->_getReportDescriptor(); return m_hidDev->_getReportDescriptor();
return {}; return {};

View File

@ -1,5 +1,8 @@
#include "boo/inputdev/DeviceFinder.hpp" #include "boo/inputdev/DeviceFinder.hpp"
#include <cstdio>
#include <cstdlib>
#if _WIN32 #if _WIN32
#include <Dbt.h> #include <Dbt.h>
#include <hidclass.h> #include <hidclass.h>
@ -10,6 +13,79 @@ namespace boo {
DeviceFinder* DeviceFinder::skDevFinder = nullptr; DeviceFinder* DeviceFinder::skDevFinder = nullptr;
DeviceFinder::DeviceFinder(std::unordered_set<uint64_t> types) {
if (skDevFinder) {
fmt::print(stderr, fmt("only one instance of CDeviceFinder may be constructed"));
std::abort();
}
skDevFinder = this;
for (const uint64_t& typeHash : types) {
const DeviceSignature* sigIter = BOO_DEVICE_SIGS;
while (sigIter->m_name) {
if (sigIter->m_typeHash == typeHash)
m_types.push_back(sigIter);
++sigIter;
}
}
}
DeviceFinder::~DeviceFinder() {
if (m_listener)
m_listener->stopScanning();
skDevFinder = nullptr;
}
bool DeviceFinder::_insertToken(std::unique_ptr<DeviceToken>&& token) {
if (!DeviceSignature::DeviceMatchToken(*token, m_types)) {
return false;
}
m_tokensLock.lock();
const TInsertedDeviceToken insertedTok = m_tokens.emplace(token->getDevicePath(), std::move(token));
m_tokensLock.unlock();
deviceConnected(*insertedTok.first->second);
return true;
}
void DeviceFinder::_removeToken(const std::string& path) {
const auto preCheck = m_tokens.find(path);
if (preCheck == m_tokens.end()) {
return;
}
DeviceToken& tok = *preCheck->second;
std::shared_ptr<DeviceBase> dev = tok.m_connectedDev;
tok._deviceClose();
deviceDisconnected(tok, dev.get());
m_tokensLock.lock();
m_tokens.erase(preCheck);
m_tokensLock.unlock();
}
bool DeviceFinder::startScanning() {
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
return m_listener->startScanning();
return false;
}
bool DeviceFinder::stopScanning() {
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
return m_listener->stopScanning();
return false;
}
bool DeviceFinder::scanNow() {
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
return m_listener->scanNow();
return false;
}
#if _WIN32 && !WINDOWS_STORE #if _WIN32 && !WINDOWS_STORE
/* Windows-specific WM_DEVICECHANGED handler */ /* Windows-specific WM_DEVICECHANGED handler */
LRESULT DeviceFinder::winDevChangedHandler(WPARAM wParam, LPARAM lParam) { LRESULT DeviceFinder::winDevChangedHandler(WPARAM wParam, LPARAM lParam) {

View File

@ -1,7 +1,7 @@
#include "boo/inputdev/DeviceSignature.hpp" #include "boo/inputdev/DeviceSignature.hpp"
#include "boo/inputdev/DeviceToken.hpp" #include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/GenericPad.hpp" #include "boo/inputdev/GenericPad.hpp"
#include "IHIDDevice.hpp" #include "lib/inputdev/IHIDDevice.hpp"
namespace boo { namespace boo {

View File

@ -1,5 +1,6 @@
#include "boo/inputdev/DolphinSmashAdapter.hpp" #include "boo/inputdev/DolphinSmashAdapter.hpp"
#include "boo/inputdev/DeviceSignature.hpp" #include "boo/inputdev/DeviceSignature.hpp"
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
@ -54,7 +55,7 @@ void DolphinSmashAdapter::transferCycle() {
if (recvSz != 37 || payload[0] != 0x21) if (recvSz != 37 || payload[0] != 0x21)
return; return;
// printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]); // fmt::print("RECEIVED DATA {} {:02X}\n", recvSz, payload[0]);
std::lock_guard<std::mutex> lk(m_callbackLock); std::lock_guard<std::mutex> lk(m_callbackLock);
if (!m_callback) if (!m_callback)

View File

@ -1,10 +1,11 @@
#include "boo/inputdev/DualshockPad.hpp" #include "boo/inputdev/DualshockPad.hpp"
#include "boo/inputdev/DeviceSignature.hpp" #include "boo/inputdev/DeviceSignature.hpp"
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include <cmath> #include <cmath>
#include <iostream>
#include <cstdio> #include <cstdio>
#include <memory.h> #include <cstring>
#include <iostream>
#ifdef _MSC_VER #ifdef _MSC_VER
inline uint16_t bswap16(uint16_t val) { return _byteswap_ushort(val); } inline uint16_t bswap16(uint16_t val) { return _byteswap_ushort(val); }
@ -42,16 +43,20 @@ void DualshockPad::deviceDisconnected() {
void DualshockPad::initialCycle() { void DualshockPad::initialCycle() {
#if 0 #if 0
uint8_t setupCommand[5] = {0xF4, 0x42, 0x0c, 0x00, 0x00}; //Tells controller to start sending changes on in pipe // Tells controller to start sending changes on in pipe
if (!sendHIDReport(setupCommand, 5, HIDReportType::Feature, 0xF4)) uint8_t setupCommand[5] = {0xF4, 0x42, 0x0c, 0x00, 0x00};
{
deviceError("Unable to send complete packet! Request size %x\n", sizeof(setupCommand)); if (!sendHIDReport(setupCommand, 5, HIDReportType::Feature, 0xF4)) {
return; deviceError("Unable to send complete packet! Request size {:x}\n", sizeof(setupCommand));
} return;
uint8_t btAddr[8]; }
receiveHIDReport(btAddr, sizeof(btAddr), HIDReportType::Feature, 0xF5);
for (int i = 0; i < 6; i++) uint8_t btAddr[8];
m_btAddress[5 - i] = btAddr[i + 2]; // Copy into buffer reversed, so it is LSB first receiveHIDReport(btAddr, sizeof(btAddr), HIDReportType::Feature, 0xF5);
for (int i = 0; i < 6; i++) {
// Copy into buffer reversed, so it is LSB first
m_btAddress[5 - i] = btAddr[i + 2];
}
#endif #endif
} }

View File

@ -8,13 +8,12 @@ class HIDListenerBSD final : public IHIDListener {
public: public:
HIDListenerBSD(DeviceFinder& finder) : m_finder(finder) {} HIDListenerBSD(DeviceFinder& finder) : m_finder(finder) {}
~HIDListenerBSD() override = default;
~HIDListenerBSD() {} bool startScanning() override { return false; }
bool stopScanning() override { return false; }
bool startScanning() { return false; } bool scanNow() override { return false; }
bool stopScanning() { return false; }
bool scanNow() { return false; }
}; };
IHIDListener* IHIDListenerNew(DeviceFinder& finder) { return new HIDListenerBSD(finder); } IHIDListener* IHIDListenerNew(DeviceFinder& finder) { return new HIDListenerBSD(finder); }

View File

@ -1,9 +1,12 @@
#include "IHIDDevice.hpp" #include "lib/inputdev/IHIDDevice.hpp"
#include <thread>
#include "lib/inputdev/IOKitPointer.hpp"
#include <IOKit/hid/IOHIDLib.h> #include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDDevicePlugin.h> #include <IOKit/hid/IOHIDDevicePlugin.h>
#include <IOKit/usb/IOUSBLib.h> #include <IOKit/usb/IOUSBLib.h>
#include "IOKitPointer.hpp"
#include <thread>
namespace boo { namespace boo {
@ -23,7 +26,7 @@ class HIDDeviceIOKit : public IHIDDevice {
std::condition_variable m_initCond; std::condition_variable m_initCond;
std::thread m_thread; std::thread m_thread;
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) override {
if (m_usbIntf) { if (m_usbIntf) {
IOReturn res = m_usbIntf->WritePipe(m_usbIntf.storage(), m_usbIntfOutPipe, (void*)data, length); IOReturn res = m_usbIntf->WritePipe(m_usbIntf.storage(), m_usbIntfOutPipe, (void*)data, length);
return res == kIOReturnSuccess; return res == kIOReturnSuccess;
@ -31,7 +34,7 @@ class HIDDeviceIOKit : public IHIDDevice {
return false; return false;
} }
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) override {
if (m_usbIntf) { if (m_usbIntf) {
UInt32 readSize = length; UInt32 readSize = length;
IOReturn res = m_usbIntf->ReadPipe(m_usbIntf.storage(), m_usbIntfInPipe, data, &readSize); IOReturn res = m_usbIntf->ReadPipe(m_usbIntf.storage(), m_usbIntfInPipe, data, &readSize);
@ -42,7 +45,7 @@ class HIDDeviceIOKit : public IHIDDevice {
return 0; return 0;
} }
std::vector<uint8_t> _getReportDescriptor() { std::vector<uint8_t> _getReportDescriptor() override {
if (m_hidIntf) { if (m_hidIntf) {
if (CFTypeRef desc = IOHIDDeviceGetProperty(m_hidIntf.get(), CFSTR(kIOHIDReportDescriptorKey))) { if (CFTypeRef desc = IOHIDDeviceGetProperty(m_hidIntf.get(), CFSTR(kIOHIDReportDescriptorKey))) {
CFIndex len = CFDataGetLength(CFDataRef(desc)); CFIndex len = CFDataGetLength(CFDataRef(desc));
@ -54,7 +57,7 @@ class HIDDeviceIOKit : public IHIDDevice {
return {}; return {};
} }
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override {
/* HACK: A bug in IOBluetoothGamepadHIDDriver prevents raw output report transmission /* HACK: A bug in IOBluetoothGamepadHIDDriver prevents raw output report transmission
* USB driver appears to work correctly */ * USB driver appears to work correctly */
if (m_hidIntf && !m_isBt) { if (m_hidIntf && !m_isBt) {
@ -64,7 +67,7 @@ class HIDDeviceIOKit : public IHIDDevice {
return false; return false;
} }
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override {
if (m_hidIntf) { if (m_hidIntf) {
CFIndex readSize = length; CFIndex readSize = length;
IOReturn res = IOHIDDeviceGetReport(m_hidIntf.get(), IOHIDReportType(tp), message, data, &readSize); IOReturn res = IOHIDDeviceGetReport(m_hidIntf.get(), IOHIDReportType(tp), message, data, &readSize);
@ -273,13 +276,13 @@ class HIDDeviceIOKit : public IHIDDevice {
device->m_hidIntf.reset(); device->m_hidIntf.reset();
} }
void _deviceDisconnected() { m_runningTransferLoop = false; } void _deviceDisconnected() override { m_runningTransferLoop = false; }
public: public:
HIDDeviceIOKit(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) HIDDeviceIOKit(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {} : m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _startThread() { void _startThread() override {
std::unique_lock<std::mutex> lk(m_initMutex); std::unique_lock<std::mutex> lk(m_initMutex);
DeviceType dType = m_token.getDeviceType(); DeviceType dType = m_token.getDeviceType();
if (dType == DeviceType::USB) if (dType == DeviceType::USB)
@ -295,7 +298,7 @@ public:
m_initCond.wait(lk); m_initCond.wait(lk);
} }
~HIDDeviceIOKit() { ~HIDDeviceIOKit() override {
m_runningTransferLoop = false; m_runningTransferLoop = false;
if (m_thread.joinable()) if (m_thread.joinable())
m_thread.detach(); m_thread.detach();

View File

@ -1,4 +1,4 @@
#include "IHIDDevice.hpp" #include "lib/inputdev/IHIDDevice.hpp"
namespace boo { namespace boo {
@ -11,13 +11,13 @@ public:
HIDDeviceNX(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) HIDDeviceNX(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {} : m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _deviceDisconnected() {} void _deviceDisconnected() override {}
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { return false; } bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) override { return false; }
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { return 0; } size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) override { return 0; }
std::vector<uint8_t> _getReportDescriptor() { return {}; } std::vector<uint8_t> _getReportDescriptor() override { return {}; }
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { return false; } bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override { return false; }
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { return 0; } size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override { return 0; }
void _startThread() {} void _startThread() override {}
}; };
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) { std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {

View File

@ -1,5 +1,7 @@
#define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */ #define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */
#include "IHIDDevice.hpp"
#include "lib/inputdev/IHIDDevice.hpp"
#include "boo/inputdev/DeviceToken.hpp" #include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/DeviceBase.hpp" #include "boo/inputdev/DeviceBase.hpp"
@ -9,12 +11,12 @@ class HIDDeviceUWP : public IHIDDevice {
public: public:
HIDDeviceUWP(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {} HIDDeviceUWP(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {}
void _deviceDisconnected() {} void _deviceDisconnected() override {}
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { return false; } bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) override { return false; }
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { return 0; } size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) override { return 0; }
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { return false; } bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override { return false; }
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { return false; } size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override { return false; }
void _startThread() {} void _startThread() override {}
}; };
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) { std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {

View File

@ -1,22 +1,24 @@
#include "IHIDDevice.hpp" #include "lib/inputdev/IHIDDevice.hpp"
#include <condition_variable>
#include <cstdio>
#include <cstring>
#include <mutex>
#include <thread>
#include "boo/inputdev/DeviceToken.hpp" #include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/DeviceBase.hpp" #include "boo/inputdev/DeviceBase.hpp"
#include <thread> #include "boo/inputdev/HIDParser.hpp"
#include <mutex>
#include <condition_variable>
#include <cstdio> #include <fcntl.h>
#include <libudev.h> #include <libudev.h>
#include <stropts.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usbdevice_fs.h> #include <linux/usbdevice_fs.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/hidraw.h> #include <linux/hidraw.h>
#include <fcntl.h> #include <stropts.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
#include <cstring>
#include "boo/inputdev/HIDParser.hpp"
namespace boo { namespace boo {
@ -40,7 +42,7 @@ class HIDDeviceUdev final : public IHIDDevice {
std::condition_variable m_initCond; std::condition_variable m_initCond;
std::thread m_thread; std::thread m_thread;
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) override {
if (m_devFd) { if (m_devFd) {
usbdevfs_bulktransfer xfer = {m_usbIntfOutPipe | USB_DIR_OUT, (unsigned)length, 30, (void*)data}; usbdevfs_bulktransfer xfer = {m_usbIntfOutPipe | USB_DIR_OUT, (unsigned)length, 30, (void*)data};
int ret = ioctl(m_devFd, USBDEVFS_BULK, &xfer); int ret = ioctl(m_devFd, USBDEVFS_BULK, &xfer);
@ -51,7 +53,7 @@ class HIDDeviceUdev final : public IHIDDevice {
return false; return false;
} }
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) override {
if (m_devFd) { if (m_devFd) {
usbdevfs_bulktransfer xfer = {m_usbIntfInPipe | USB_DIR_IN, (unsigned)length, 30, data}; usbdevfs_bulktransfer xfer = {m_usbIntfInPipe | USB_DIR_IN, (unsigned)length, 30, data};
return ioctl(m_devFd, USBDEVFS_BULK, &xfer); return ioctl(m_devFd, USBDEVFS_BULK, &xfer);
@ -102,7 +104,7 @@ class HIDDeviceUdev final : public IHIDDevice {
} }
/* Request that kernel disconnects existing driver */ /* Request that kernel disconnects existing driver */
usbdevfs_ioctl disconnectReq = {0, USBDEVFS_DISCONNECT, NULL}; usbdevfs_ioctl disconnectReq = {0, USBDEVFS_DISCONNECT, nullptr};
ioctl(fd, USBDEVFS_IOCTL, &disconnectReq); ioctl(fd, USBDEVFS_IOCTL, &disconnectReq);
/* Return control to main thread */ /* Return control to main thread */
@ -209,9 +211,9 @@ class HIDDeviceUdev final : public IHIDDevice {
udev_device_unref(udevDev); udev_device_unref(udevDev);
} }
void _deviceDisconnected() { m_runningTransferLoop = false; } void _deviceDisconnected() override { m_runningTransferLoop = false; }
std::vector<uint8_t> _getReportDescriptor() { std::vector<uint8_t> _getReportDescriptor() override {
/* Report descriptor size */ /* Report descriptor size */
int reportDescSize; int reportDescSize;
if (ioctl(m_devFd, HIDIOCGRDESCSIZE, &reportDescSize) == -1) if (ioctl(m_devFd, HIDIOCGRDESCSIZE, &reportDescSize) == -1)
@ -227,7 +229,7 @@ class HIDDeviceUdev final : public IHIDDevice {
return ret; return ret;
} }
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override {
if (m_devFd) { if (m_devFd) {
if (tp == HIDReportType::Feature) { if (tp == HIDReportType::Feature) {
int ret = ioctl(m_devFd, HIDIOCSFEATURE(length), data); int ret = ioctl(m_devFd, HIDIOCSFEATURE(length), data);
@ -244,7 +246,7 @@ class HIDDeviceUdev final : public IHIDDevice {
return false; return false;
} }
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override {
if (m_devFd) { if (m_devFd) {
if (tp == HIDReportType::Feature) { if (tp == HIDReportType::Feature) {
data[0] = message; data[0] = message;
@ -261,7 +263,7 @@ public:
HIDDeviceUdev(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) HIDDeviceUdev(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {} : m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _startThread() { void _startThread() override {
std::unique_lock<std::mutex> lk(m_initMutex); std::unique_lock<std::mutex> lk(m_initMutex);
DeviceType dType = m_token.getDeviceType(); DeviceType dType = m_token.getDeviceType();
if (dType == DeviceType::USB) if (dType == DeviceType::USB)
@ -277,7 +279,7 @@ public:
m_initCond.wait(lk); m_initCond.wait(lk);
} }
~HIDDeviceUdev() { ~HIDDeviceUdev() override {
m_runningTransferLoop = false; m_runningTransferLoop = false;
if (m_thread.joinable()) if (m_thread.joinable())
m_thread.detach(); m_thread.detach();

View File

@ -1,13 +1,15 @@
#define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */ #define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */
#include "IHIDDevice.hpp" #include "lib/inputdev/IHIDDevice.hpp"
#include "boo/inputdev/DeviceToken.hpp" #include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/DeviceBase.hpp" #include "boo/inputdev/DeviceBase.hpp"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <cstring>
#include <cstdio>
#include <algorithm> #include <algorithm>
#include <condition_variable>
#include <cstdio>
#include <cstring>
#include <mutex>
#include <thread>
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1 #define WIN32_LEAN_AND_MEAN 1
@ -27,8 +29,8 @@ class HIDDeviceWinUSB final : public IHIDDevice {
DeviceToken& m_token; DeviceToken& m_token;
std::shared_ptr<DeviceBase> m_devImp; std::shared_ptr<DeviceBase> m_devImp;
HANDLE m_devHandle = 0; HANDLE m_devHandle = nullptr;
HANDLE m_hidHandle = 0; HANDLE m_hidHandle = nullptr;
WINUSB_INTERFACE_HANDLE m_usbHandle = nullptr; WINUSB_INTERFACE_HANDLE m_usbHandle = nullptr;
unsigned m_usbIntfInPipe = 0; unsigned m_usbIntfInPipe = 0;
unsigned m_usbIntfOutPipe = 0; unsigned m_usbIntfOutPipe = 0;
@ -39,21 +41,22 @@ class HIDDeviceWinUSB final : public IHIDDevice {
std::condition_variable m_initCond; std::condition_variable m_initCond;
std::thread m_thread; std::thread m_thread;
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) override {
if (m_usbHandle) { if (m_usbHandle) {
ULONG lengthTransferred = 0; ULONG lengthTransferred = 0;
if (!WinUsb_WritePipe(m_usbHandle, m_usbIntfOutPipe, (PUCHAR)data, (ULONG)length, &lengthTransferred, NULL) || if (!WinUsb_WritePipe(m_usbHandle, m_usbIntfOutPipe, (PUCHAR)data, (ULONG)length, &lengthTransferred, nullptr) ||
lengthTransferred != length) lengthTransferred != length) {
return false; return false;
}
return true; return true;
} }
return false; return false;
} }
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) override {
if (m_usbHandle) { if (m_usbHandle) {
ULONG lengthTransferred = 0; ULONG lengthTransferred = 0;
if (!WinUsb_ReadPipe(m_usbHandle, m_usbIntfInPipe, (PUCHAR)data, (ULONG)length, &lengthTransferred, NULL)) if (!WinUsb_ReadPipe(m_usbHandle, m_usbIntfInPipe, (PUCHAR)data, (ULONG)length, &lengthTransferred, nullptr))
return 0; return 0;
return lengthTransferred; return lengthTransferred;
} }
@ -66,8 +69,8 @@ class HIDDeviceWinUSB final : public IHIDDevice {
/* POSIX.. who needs it?? -MS */ /* POSIX.. who needs it?? -MS */
device->m_devHandle = device->m_devHandle =
CreateFileA(device->m_devPath.data(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CreateFileA(device->m_devPath.data(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr);
if (INVALID_HANDLE_VALUE == device->m_devHandle) { if (INVALID_HANDLE_VALUE == device->m_devHandle) {
device->m_devImp->deviceError(fmt("Unable to open {}@{}: {}\n"), device->m_devImp->deviceError(fmt("Unable to open {}@{}: {}\n"),
device->m_token.getProductName(), device->m_devPath, GetLastError()); device->m_token.getProductName(), device->m_devPath, GetLastError());
@ -150,8 +153,8 @@ class HIDDeviceWinUSB final : public IHIDDevice {
/* POSIX.. who needs it?? -MS */ /* POSIX.. who needs it?? -MS */
device->m_overlapped.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); device->m_overlapped.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
device->m_hidHandle = device->m_hidHandle =
CreateFileA(device->m_devPath.data(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CreateFileA(device->m_devPath.data(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr);
if (INVALID_HANDLE_VALUE == device->m_hidHandle) { if (INVALID_HANDLE_VALUE == device->m_hidHandle) {
device->m_devImp->deviceError(fmt("Unable to open {}@{}: {}\n"), device->m_devImp->deviceError(fmt("Unable to open {}@{}: {}\n"),
device->m_token.getProductName(), device->m_devPath, GetLastError()); device->m_token.getProductName(), device->m_devPath, GetLastError());
@ -199,14 +202,14 @@ class HIDDeviceWinUSB final : public IHIDDevice {
device->m_hidHandle = nullptr; device->m_hidHandle = nullptr;
} }
void _deviceDisconnected() { m_runningTransferLoop = false; } void _deviceDisconnected() override { m_runningTransferLoop = false; }
std::vector<uint8_t> m_sendBuf; std::vector<uint8_t> m_sendBuf;
std::vector<uint8_t> m_recvBuf; std::vector<uint8_t> m_recvBuf;
const PHIDP_PREPARSED_DATA _getReportDescriptor() { return m_preparsedData; } const PHIDP_PREPARSED_DATA _getReportDescriptor() override { return m_preparsedData; }
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override {
size_t maxOut = std::max(m_minFeatureSz, std::max(m_minOutputSz, length)); size_t maxOut = std::max(m_minFeatureSz, std::max(m_minOutputSz, length));
if (m_sendBuf.size() < maxOut) if (m_sendBuf.size() < maxOut)
m_sendBuf.resize(maxOut); m_sendBuf.resize(maxOut);
@ -250,7 +253,7 @@ class HIDDeviceWinUSB final : public IHIDDevice {
return true; return true;
} }
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) { size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) override {
size_t maxIn = std::max(m_minFeatureSz, std::max(m_minInputSz, length)); size_t maxIn = std::max(m_minFeatureSz, std::max(m_minInputSz, length));
if (m_recvBuf.size() < maxIn) if (m_recvBuf.size() < maxIn)
m_recvBuf.resize(maxIn); m_recvBuf.resize(maxIn);
@ -273,7 +276,7 @@ public:
HIDDeviceWinUSB(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) HIDDeviceWinUSB(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {} : m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _startThread() { void _startThread() override {
std::unique_lock<std::mutex> lk(m_initMutex); std::unique_lock<std::mutex> lk(m_initMutex);
DeviceType dType = m_token.getDeviceType(); DeviceType dType = m_token.getDeviceType();
if (dType == DeviceType::USB) if (dType == DeviceType::USB)
@ -287,7 +290,7 @@ public:
m_initCond.wait(lk); m_initCond.wait(lk);
} }
~HIDDeviceWinUSB() { ~HIDDeviceWinUSB() override {
m_runningTransferLoop = false; m_runningTransferLoop = false;
if (m_thread.joinable()) if (m_thread.joinable())
m_thread.detach(); m_thread.detach();

View File

@ -16,8 +16,7 @@ class HIDDeviceBSD final : public IHIDDevice {
public: public:
HIDDeviceBSD(DeviceToken& token, DeviceBase& devImp) : m_token(token), m_devImp(devImp) {} HIDDeviceBSD(DeviceToken& token, DeviceBase& devImp) : m_token(token), m_devImp(devImp) {}
~HIDDeviceBSD() override = default;
~HIDDeviceBSD() {}
}; };
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) { std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {

View File

@ -108,7 +108,7 @@ class HIDListenerIOKit : public IHIDListener {
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB, vid, pid, vstr, pstr, devPath)); listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB, vid, pid, vstr, pstr, devPath));
// printf("ADDED %08X %s\n", obj.get(), devPath); // fmt::print(fmt("ADDED {:08X} {}\n"), obj.get(), devPath);
} }
} }
@ -124,7 +124,7 @@ class HIDListenerIOKit : public IHIDListener {
if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0) if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0)
continue; continue;
listener->m_finder._removeToken(devPath); listener->m_finder._removeToken(devPath);
// printf("REMOVED %08X %s\n", obj.get(), devPath); // fmt::print(fmt("REMOVED {:08X} {}\n"), obj.get(), devPath);
} }
} }
@ -191,7 +191,7 @@ class HIDListenerIOKit : public IHIDListener {
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID, vidv, pidv, vstr, pstr, devPath)); listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID, vidv, pidv, vstr, pstr, devPath));
// printf("ADDED %08X %s\n", obj, devPath); // fmt::print(fmt("ADDED {:08X} {}\n"), obj, devPath);
} }
} }
@ -207,7 +207,7 @@ class HIDListenerIOKit : public IHIDListener {
if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0) if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0)
continue; continue;
listener->m_finder._removeToken(devPath); listener->m_finder._removeToken(devPath);
// printf("REMOVED %08X %s\n", obj, devPath); // fmt::print(fmt("REMOVED {:08X} {}\n"), obj, devPath);
} }
} }
@ -263,23 +263,23 @@ public:
m_scanningEnabled = false; m_scanningEnabled = false;
} }
~HIDListenerIOKit() { ~HIDListenerIOKit() override {
// CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode); // CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode);
IONotificationPortDestroy(m_llPort); IONotificationPortDestroy(m_llPort);
} }
/* Automatic device scanning */ /* Automatic device scanning */
bool startScanning() { bool startScanning() override {
m_scanningEnabled = true; m_scanningEnabled = true;
return true; return true;
} }
bool stopScanning() { bool stopScanning() override {
m_scanningEnabled = false; m_scanningEnabled = false;
return true; return true;
} }
/* Manual device scanning */ /* Manual device scanning */
bool scanNow() { bool scanNow() override {
IOObjectPointer<io_iterator_t> iter; IOObjectPointer<io_iterator_t> iter;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(m_usbClass), &iter) == kIOReturnSuccess) { if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(m_usbClass), &iter) == kIOReturnSuccess) {
devicesConnectedUSBLL(this, iter.get()); devicesConnectedUSBLL(this, iter.get());

View File

@ -8,9 +8,9 @@ class HIDListenerNX : public IHIDListener {
public: public:
HIDListenerNX(DeviceFinder& finder) : m_finder(finder) {} HIDListenerNX(DeviceFinder& finder) : m_finder(finder) {}
bool startScanning() { return false; } bool startScanning() override { return false; }
bool stopScanning() { return false; } bool stopScanning() override { return false; }
bool scanNow() { return false; } bool scanNow() override { return false; }
}; };
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) { return std::make_unique<HIDListenerNX>(finder); } std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) { return std::make_unique<HIDListenerNX>(finder); }

View File

@ -1,4 +1,5 @@
#define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */ #define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */
#include "boo/inputdev/IHIDListener.hpp" #include "boo/inputdev/IHIDListener.hpp"
#include "boo/inputdev/DeviceFinder.hpp" #include "boo/inputdev/DeviceFinder.hpp"
@ -9,11 +10,11 @@ public:
HIDListenerUWP(DeviceFinder& finder) {} HIDListenerUWP(DeviceFinder& finder) {}
/* Automatic device scanning */ /* Automatic device scanning */
bool startScanning() { return false; } bool startScanning() override { return false; }
bool stopScanning() { return false; } bool stopScanning() override { return false; }
/* Manual device scanning */ /* Manual device scanning */
bool scanNow() { return false; } bool scanNow() override { return false; }
}; };
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) { return std::make_unique<HIDListenerUWP>(finder); } std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) { return std::make_unique<HIDListenerUWP>(finder); }

View File

@ -118,14 +118,14 @@ class HIDListenerUdev final : public IHIDListener {
} }
#if 0 #if 0
udev_list_entry* att = nullptr; udev_list_entry* att = nullptr;
udev_list_entry_foreach(att, attrs) udev_list_entry_foreach(att, attrs)
{ {
const char* name = udev_list_entry_get_name(att); const char* name = udev_list_entry_get_name(att);
const char* val = udev_list_entry_get_value(att); const char* val = udev_list_entry_get_value(att);
fprintf(stderr, "%s %s\n", name, val); fmt::print(stderr, fmt("{} {}\n"), name, val);
} }
fprintf(stderr, "\n\n"); std::fputs("\n\n", stderr);
#endif #endif
m_finder._insertToken(std::make_unique<DeviceToken>(type, vid, pid, manuf, product, devPath)); m_finder._insertToken(std::make_unique<DeviceToken>(type, vid, pid, manuf, product, devPath));
@ -187,7 +187,7 @@ public:
m_udevThread = std::thread(std::bind(&HIDListenerUdev::_udevProc, this), this); m_udevThread = std::thread(std::bind(&HIDListenerUdev::_udevProc, this), this);
} }
~HIDListenerUdev() { ~HIDListenerUdev() override {
pthread_cancel(m_udevThread.native_handle()); pthread_cancel(m_udevThread.native_handle());
if (m_udevThread.joinable()) if (m_udevThread.joinable())
m_udevThread.join(); m_udevThread.join();
@ -195,17 +195,17 @@ public:
} }
/* Automatic device scanning */ /* Automatic device scanning */
bool startScanning() { bool startScanning() override {
m_scanningEnabled = true; m_scanningEnabled = true;
return true; return true;
} }
bool stopScanning() { bool stopScanning() override {
m_scanningEnabled = false; m_scanningEnabled = false;
return true; return true;
} }
/* Manual device scanning */ /* Manual device scanning */
bool scanNow() { bool scanNow() override {
udev_enumerate* uenum = udev_enumerate_new(GetUdev()); udev_enumerate* uenum = udev_enumerate_new(GetUdev());
udev_enumerate_add_match_subsystem(uenum, "usb"); udev_enumerate_add_match_subsystem(uenum, "usb");
udev_enumerate_add_match_subsystem(uenum, "bluetooth"); udev_enumerate_add_match_subsystem(uenum, "bluetooth");

View File

@ -1,10 +1,13 @@
#define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */ #define _CRT_SECURE_NO_WARNINGS 1 /* STFU MSVC */
#include "boo/inputdev/IHIDListener.hpp" #include "boo/inputdev/IHIDListener.hpp"
#include "boo/inputdev/DeviceFinder.hpp"
#include "boo/inputdev/XInputPad.hpp"
#include <cstring> #include <cstring>
#include <thread> #include <thread>
#include "boo/inputdev/DeviceFinder.hpp"
#include "boo/inputdev/XInputPad.hpp"
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1 #define WIN32_LEAN_AND_MEAN 1
#endif #endif
@ -51,17 +54,17 @@ class HIDListenerWinUSB final : public IHIDListener {
CHAR szVid[MAX_DEVICE_ID_LEN], szPid[MAX_DEVICE_ID_LEN], szMi[MAX_DEVICE_ID_LEN]; CHAR szVid[MAX_DEVICE_ID_LEN], szPid[MAX_DEVICE_ID_LEN], szMi[MAX_DEVICE_ID_LEN];
/* List all connected HID devices */ /* List all connected HID devices */
hDevInfo = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE); hDevInfo = SetupDiGetClassDevs(nullptr, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) if (hDevInfo == INVALID_HANDLE_VALUE)
return; return;
for (i = 0;; ++i) { for (i = 0;; ++i) {
if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, TypeGUID, i, &DeviceInterfaceData)) if (!SetupDiEnumDeviceInterfaces(hDevInfo, nullptr, TypeGUID, i, &DeviceInterfaceData))
break; break;
DeviceInterfaceDetailData.wtf.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); DeviceInterfaceDetailData.wtf.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetailA(hDevInfo, &DeviceInterfaceData, &DeviceInterfaceDetailData.wtf, if (!SetupDiGetDeviceInterfaceDetailA(hDevInfo, &DeviceInterfaceData, &DeviceInterfaceDetailData.wtf,
sizeof(DeviceInterfaceDetailData), NULL, &DeviceInfoData)) sizeof(DeviceInterfaceDetailData), nullptr, &DeviceInfoData))
continue; continue;
r = CM_Get_Device_IDA(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 0); r = CM_Get_Device_IDA(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 0);
@ -73,7 +76,7 @@ class HIDListenerWinUSB final : public IHIDListener {
szVid[0] = '\0'; szVid[0] = '\0';
szPid[0] = '\0'; szPid[0] = '\0';
szMi[0] = '\0'; szMi[0] = '\0';
while (pszToken != NULL) { while (pszToken != nullptr) {
for (j = 0; j < 3; ++j) { for (j = 0; j < 3; ++j) {
if (strncmp(pszToken, arPrefix[j], 4) == 0) { if (strncmp(pszToken, arPrefix[j], 4) == 0) {
switch (j) { switch (j) {
@ -91,14 +94,14 @@ class HIDListenerWinUSB final : public IHIDListener {
} }
} }
} }
pszToken = strtok_s(NULL, "\\#&", &pszNextToken); pszToken = strtok_s(nullptr, "\\#&", &pszNextToken);
} }
if (!szVid[0] || !szPid[0]) if (!szVid[0] || !szPid[0])
continue; continue;
unsigned vid = strtol(szVid + 4, NULL, 16); unsigned vid = strtol(szVid + 4, nullptr, 16);
unsigned pid = strtol(szPid + 4, NULL, 16); unsigned pid = strtol(szPid + 4, nullptr, 16);
CHAR productW[1024] = {0}; CHAR productW[1024] = {0};
// CHAR product[1024] = {0}; // CHAR product[1024] = {0};
@ -121,8 +124,8 @@ class HIDListenerWinUSB final : public IHIDListener {
if (type == DeviceType::HID) { if (type == DeviceType::HID) {
HANDLE devHnd = CreateFileA(DeviceInterfaceDetailData.wtf.DevicePath, GENERIC_WRITE | GENERIC_READ, HANDLE devHnd = CreateFileA(DeviceInterfaceDetailData.wtf.DevicePath, GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, nullptr);
if (INVALID_HANDLE_VALUE == devHnd) if (INVALID_HANDLE_VALUE == devHnd)
continue; continue;
PHIDP_PREPARSED_DATA preparsedData; PHIDP_PREPARSED_DATA preparsedData;
@ -227,29 +230,29 @@ public:
} }
} }
~HIDListenerWinUSB() { ~HIDListenerWinUSB() override {
m_xinputRunning = false; m_xinputRunning = false;
if (m_xinputThread.joinable()) if (m_xinputThread.joinable())
m_xinputThread.join(); m_xinputThread.join();
} }
/* Automatic device scanning */ /* Automatic device scanning */
bool startScanning() { bool startScanning() override {
m_scanningEnabled = true; m_scanningEnabled = true;
return true; return true;
} }
bool stopScanning() { bool stopScanning() override {
m_scanningEnabled = false; m_scanningEnabled = false;
return true; return true;
} }
/* Manual device scanning */ /* Manual device scanning */
bool scanNow() { bool scanNow() override {
_pollDevices(nullptr); _pollDevices(nullptr);
return true; return true;
} }
bool _extDevConnect(const char* path) { bool _extDevConnect(const char* path) override {
char upperPath[1024]; char upperPath[1024];
strcpy_s(upperPath, 1024, path); strcpy_s(upperPath, 1024, path);
CharUpperA(upperPath); CharUpperA(upperPath);
@ -258,7 +261,7 @@ public:
return true; return true;
} }
bool _extDevDisconnect(const char* path) { bool _extDevDisconnect(const char* path) override {
char upperPath[1024]; char upperPath[1024];
strcpy_s(upperPath, 1024, path); strcpy_s(upperPath, 1024, path);
CharUpperA(upperPath); CharUpperA(upperPath);

View File

@ -1,6 +1,8 @@
#include "boo/inputdev/HIDParser.hpp" #include "boo/inputdev/HIDParser.hpp"
#include <map>
#include <algorithm> #include <algorithm>
#include <array>
#include <map>
#undef min #undef min
#undef max #undef max
@ -11,251 +13,257 @@ namespace boo {
* http://www.usb.org/developers/hidpage/HID1_11.pdf * http://www.usb.org/developers/hidpage/HID1_11.pdf
*/ */
static const char* UsagePageNames[] = {"Undefined", "Generic Desktop", "Simulation", "VR", "Sport", constexpr std::array<const char*, 14> UsagePageNames{
"Game Controls", "Generic Device", "Keyboard", "LEDs", "Button", "Undefined", "Generic Desktop", "Simulation", "VR", "Sport",
"Ordinal", "Telephony", "Consumer", "Digitizer"}; "Game Controls", "Generic Device", "Keyboard", "LEDs", "Button",
"Ordinal", "Telephony", "Consumer", "Digitizer",
};
static const char* GenericDesktopUsages[] = {"Undefined", constexpr std::array<const char*, 182> GenericDesktopUsages{
"Pointer", "Undefined",
"Mouse", "Pointer",
"Reserved", "Mouse",
"Joystick", "Reserved",
"Game Pad", "Joystick",
"Keyboard", "Game Pad",
"Keypad", "Keyboard",
"Multi-axis Controller", "Keypad",
"Tablet PC System Controls", "Multi-axis Controller",
nullptr, "Tablet PC System Controls",
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
"X", nullptr,
"Y", "X",
"Z", "Y",
"Rx", "Z",
"Ry", "Rx",
"Rz", "Ry",
"Slider", "Rz",
"Dial", "Slider",
"Wheel", "Dial",
"Hat Switch", "Wheel",
"Counted Buffer", "Hat Switch",
"Byte Count", "Counted Buffer",
"Motion Wakeup", "Byte Count",
"Start", "Motion Wakeup",
"Select", "Start",
"Reserved", "Select",
"Vx", "Reserved",
"Vy", "Vx",
"Vz", "Vy",
"Vbrx", "Vz",
"Vbry", "Vbrx",
"Vbrz", "Vbry",
"Vno", "Vbrz",
"Feature Notification", "Vno",
"Resolution Multiplier", "Feature Notification",
nullptr, "Resolution Multiplier",
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
"System Control", nullptr,
"System Power Down", "System Control",
"System Sleep", "System Power Down",
"System Wake Up", "System Sleep",
"System Context Menu", "System Wake Up",
"System Main Menu", "System Context Menu",
"System App Menu", "System Main Menu",
"System Menu Help", "System App Menu",
"System Menu Exit", "System Menu Help",
"System Menu Select", "System Menu Exit",
"System Menu Right", "System Menu Select",
"System Menu Left", "System Menu Right",
"System Menu Up", "System Menu Left",
"System Menu Down", "System Menu Up",
"System Cold Restart", "System Menu Down",
"System Warm Restart", "System Cold Restart",
"D-pad Up", "System Warm Restart",
"D-pad Down", "D-pad Up",
"D-pad Right", "D-pad Down",
"D-pad Left", "D-pad Right",
nullptr, "D-pad Left",
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
"System Dock", nullptr,
"System Undock", "System Dock",
"System Setup", "System Undock",
"System Break", "System Setup",
"System Debugger Break", "System Break",
"Application Break", "System Debugger Break",
"Application Debugger Break", "Application Break",
"System Speaker Mute", "Application Debugger Break",
"System Hibernate", "System Speaker Mute",
nullptr, "System Hibernate",
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
"System Display Invert", nullptr,
"System Display Internal", "System Display Invert",
"System Display External", "System Display Internal",
"System Display Both", "System Display External",
"System Display Dual", "System Display Both",
"System Display Toggle Int/Ext"}; "System Display Dual",
"System Display Toggle Int/Ext",
};
static const char* GameUsages[] = {"Undefined", constexpr std::array<const char*, 58> GameUsages{
"3D Game Controller", "Undefined",
"Pinball Device", "3D Game Controller",
"Gun Device", "Pinball Device",
nullptr, "Gun Device",
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
"Point of View", nullptr,
"Turn Right/Left", "Point of View",
"Pitch Forward/Backward", "Turn Right/Left",
"Roll Right/Left", "Pitch Forward/Backward",
"Move Right/Left", "Roll Right/Left",
"Move Forward/Backward", "Move Right/Left",
"Move Up/Down", "Move Forward/Backward",
"Lean Right/Left", "Move Up/Down",
"Lean Forward/Backward", "Lean Right/Left",
"Height of POV", "Lean Forward/Backward",
"Flipper", "Height of POV",
"Secondary Flipper", "Flipper",
"Bump", "Secondary Flipper",
"New Game", "Bump",
"Shoot Ball", "New Game",
"Player", "Shoot Ball",
"Gun Bolt", "Player",
"Gun Clip", "Gun Bolt",
"Gun Selector", "Gun Clip",
"Gun Single Shot", "Gun Selector",
"Gun Burst", "Gun Single Shot",
"Gun Automatic", "Gun Burst",
"Gun Safety", "Gun Automatic",
"Gemepad Fire/Jump", "Gun Safety",
nullptr, "Gemepad Fire/Jump",
"Gamepad Trigger"}; nullptr,
"Gamepad Trigger",
};
enum class HIDCollectionType : uint8_t { enum class HIDCollectionType : uint8_t {
Physical, Physical,
@ -380,21 +388,31 @@ HIDMainItem::HIDMainItem(uint32_t flags, HIDUsagePage usagePage, HIDUsage usage,
, m_reportSize(reportSize) {} , m_reportSize(reportSize) {}
const char* HIDMainItem::GetUsagePageName() const { const char* HIDMainItem::GetUsagePageName() const {
if (int(m_usagePage) >= std::extent<decltype(UsagePageNames)>::value) const auto index = size_t(m_usagePage);
if (index >= UsagePageNames.size()) {
return nullptr; return nullptr;
return UsagePageNames[int(m_usagePage)]; }
return UsagePageNames[index];
} }
const char* HIDMainItem::GetUsageName() const { const char* HIDMainItem::GetUsageName() const {
const auto index = size_t(m_usage);
switch (m_usagePage) { switch (m_usagePage) {
case HIDUsagePage::GenericDesktop: case HIDUsagePage::GenericDesktop:
if (int(m_usage) >= std::extent<decltype(GenericDesktopUsages)>::value) if (index >= GenericDesktopUsages.size()) {
return nullptr; return nullptr;
return GenericDesktopUsages[int(m_usage)]; }
return GenericDesktopUsages[index];
case HIDUsagePage::Game: case HIDUsagePage::Game:
if (int(m_usage) >= std::extent<decltype(GameUsages)>::value) if (index >= GameUsages.size()) {
return nullptr; return nullptr;
return GameUsages[int(m_usage)]; }
return GameUsages[index];
default: default:
return nullptr; return nullptr;
} }
@ -443,17 +461,17 @@ HIDParser::ParserStatus HIDParser::Parse(const PHIDP_PREPARSED_DATA descriptorDa
USHORT length = caps.NumberInputButtonCaps; USHORT length = caps.NumberInputButtonCaps;
std::vector<HIDP_BUTTON_CAPS> bCaps(caps.NumberInputButtonCaps, HIDP_BUTTON_CAPS()); std::vector<HIDP_BUTTON_CAPS> bCaps(caps.NumberInputButtonCaps, HIDP_BUTTON_CAPS());
HidP_GetButtonCaps(HidP_Input, bCaps.data(), &length, descriptorData); HidP_GetButtonCaps(HidP_Input, bCaps.data(), &length, descriptorData);
for (const HIDP_BUTTON_CAPS& caps : bCaps) { for (const HIDP_BUTTON_CAPS& buttonCaps : bCaps) {
if (caps.IsRange) { if (buttonCaps.IsRange) {
int usage = caps.Range.UsageMin; int usage = buttonCaps.Range.UsageMin;
for (int i = caps.Range.DataIndexMin; i <= caps.Range.DataIndexMax; ++i, ++usage) { for (int i = buttonCaps.Range.DataIndexMin; i <= buttonCaps.Range.DataIndexMax; ++i, ++usage) {
inputItems.insert(std::make_pair( inputItems.emplace(i, HIDMainItem(buttonCaps.BitField, HIDUsagePage(buttonCaps.UsagePage), HIDUsage(usage),
i, HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDUsage(usage), std::make_pair(0, 1), 1))); std::make_pair(0, 1), 1));
} }
} else { } else {
inputItems.insert(std::make_pair(caps.NotRange.DataIndex, inputItems.emplace(buttonCaps.NotRange.DataIndex,
HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDMainItem(buttonCaps.BitField, HIDUsagePage(buttonCaps.UsagePage),
HIDUsage(caps.NotRange.Usage), std::make_pair(0, 1), 1))); HIDUsage(buttonCaps.NotRange.Usage), std::make_pair(0, 1), 1));
} }
} }
} }
@ -463,19 +481,19 @@ HIDParser::ParserStatus HIDParser::Parse(const PHIDP_PREPARSED_DATA descriptorDa
USHORT length = caps.NumberInputValueCaps; USHORT length = caps.NumberInputValueCaps;
std::vector<HIDP_VALUE_CAPS> vCaps(caps.NumberInputValueCaps, HIDP_VALUE_CAPS()); std::vector<HIDP_VALUE_CAPS> vCaps(caps.NumberInputValueCaps, HIDP_VALUE_CAPS());
HidP_GetValueCaps(HidP_Input, vCaps.data(), &length, descriptorData); HidP_GetValueCaps(HidP_Input, vCaps.data(), &length, descriptorData);
for (const HIDP_VALUE_CAPS& caps : vCaps) { for (const HIDP_VALUE_CAPS& valueCaps : vCaps) {
if (caps.IsRange) { if (valueCaps.IsRange) {
int usage = caps.Range.UsageMin; int usage = valueCaps.Range.UsageMin;
for (int i = caps.Range.DataIndexMin; i <= caps.Range.DataIndexMax; ++i, ++usage) { for (int i = valueCaps.Range.DataIndexMin; i <= valueCaps.Range.DataIndexMax; ++i, ++usage) {
inputItems.insert( inputItems.emplace(i, HIDMainItem(valueCaps.BitField, HIDUsagePage(valueCaps.UsagePage), HIDUsage(usage),
std::make_pair(i, HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDUsage(usage), std::make_pair(valueCaps.LogicalMin, valueCaps.LogicalMax),
std::make_pair(caps.LogicalMin, caps.LogicalMax), caps.BitSize))); valueCaps.BitSize));
} }
} else { } else {
inputItems.insert( inputItems.emplace(valueCaps.NotRange.DataIndex,
std::make_pair(caps.NotRange.DataIndex, HIDMainItem(valueCaps.BitField, HIDUsagePage(valueCaps.UsagePage),
HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDUsage(caps.NotRange.Usage), HIDUsage(valueCaps.NotRange.Usage),
HIDRange(caps.LogicalMin, caps.LogicalMax), caps.BitSize))); HIDRange(valueCaps.LogicalMin, valueCaps.LogicalMax), valueCaps.BitSize));
} }
} }
} }
@ -804,9 +822,9 @@ void HIDParser::ScanValues(const std::function<bool(const HIDMainItem& item, int
continue; continue;
int32_t value = 0; int32_t value = 0;
if (it != end) { if (it != end) {
const HIDP_DATA& data = *it; const HIDP_DATA& hidData = *it;
if (data.DataIndex == idx) { if (hidData.DataIndex == idx) {
value = data.RawValue; value = hidData.RawValue;
++it; ++it;
} }
} }

View File

@ -1,9 +1,10 @@
#pragma once #pragma once
#include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/DeviceBase.hpp"
#include <memory> #include <memory>
#include "boo/inputdev/DeviceBase.hpp"
#include "boo/inputdev/DeviceToken.hpp"
#if _WIN32 #if _WIN32
#include <hidsdi.h> #include <hidsdi.h>
#endif #endif

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "../CFPointer.hpp" #include "lib/CFPointer.hpp"
#include <IOKit/IOTypes.h> #include <IOKit/IOTypes.h>
#include <IOKit/IOKitLib.h> #include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h> #include <IOKit/IOCFPlugIn.h>

View File

@ -1,6 +1,9 @@
#include "boo/inputdev/NintendoPowerA.hpp" #include "boo/inputdev/NintendoPowerA.hpp"
#include <cstring>
#include "boo/inputdev/DeviceSignature.hpp" #include "boo/inputdev/DeviceSignature.hpp"
#include <memory.h>
namespace boo { namespace boo {
NintendoPowerA::NintendoPowerA(DeviceToken* token) NintendoPowerA::NintendoPowerA(DeviceToken* token)
: TDeviceBase<INintendoPowerACallback>(dev_typeid(NintendoPowerA), token) {} : TDeviceBase<INintendoPowerACallback>(dev_typeid(NintendoPowerA), token) {}
@ -33,12 +36,10 @@ void NintendoPowerA::finalCycle() {}
void NintendoPowerA::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {} void NintendoPowerA::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {}
bool NintendoPowerAState::operator==(const NintendoPowerAState& other) { bool NintendoPowerAState::operator==(const NintendoPowerAState& other) const {
return !memcmp(this, &other, sizeof(NintendoPowerAState)); return memcmp(this, &other, sizeof(NintendoPowerAState)) == 0;
} }
bool NintendoPowerAState::operator!=(const NintendoPowerAState& other) { bool NintendoPowerAState::operator!=(const NintendoPowerAState& other) const { return !operator==(other); }
return memcmp(this, &other, sizeof(NintendoPowerAState));
}
} // namespace boo } // namespace boo

View File

@ -1,12 +1,13 @@
#include <AppKit/AppKit.h> #include <AppKit/AppKit.h>
#include <thread> #include <thread>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/graphicsdev/Metal.hpp" #include "boo/graphicsdev/Metal.hpp"
#include "CocoaCommon.hpp" #include "lib/Common.hpp"
#include "../Common.hpp" #include "lib/mac/CocoaCommon.hpp"
#include "logvisor/logvisor.hpp" #include <logvisor/logvisor.hpp>
#if !__has_feature(objc_arc) #if !__has_feature(objc_arc)
#error ARC Required #error ARC Required
@ -110,7 +111,7 @@ public:
Log.report(logvisor::Info, fmt("using Metal renderer")); Log.report(logvisor::Info, fmt("using Metal renderer"));
} }
EPlatformType getPlatformType() const { EPlatformType getPlatformType() const override {
return EPlatformType::Cocoa; return EPlatformType::Cocoa;
} }
@ -118,7 +119,7 @@ public:
int m_clientReturn = 0; int m_clientReturn = 0;
bool m_terminateNow = false; bool m_terminateNow = false;
int run() { int run() override {
/* Spawn client thread */ /* Spawn client thread */
m_clientThread = std::thread([&]() { m_clientThread = std::thread([&]() {
std::string thrName = std::string(getFriendlyName()) + " Client Thread"; std::string thrName = std::string(getFriendlyName()) + " Client Thread";
@ -161,23 +162,23 @@ public:
[NSApp terminate:nil]; [NSApp terminate:nil];
} }
SystemStringView getUniqueName() const { SystemStringView getUniqueName() const override {
return m_uniqueName; return m_uniqueName;
} }
SystemStringView getFriendlyName() const { SystemStringView getFriendlyName() const override {
return m_friendlyName; return m_friendlyName;
} }
SystemStringView getProcessName() const { SystemStringView getProcessName() const override {
return m_pname; return m_pname;
} }
const std::vector<SystemString>& getArgs() const { const std::vector<SystemString>& getArgs() const override {
return m_args; return m_args;
} }
std::shared_ptr<IWindow> newWindow(std::string_view title) { std::shared_ptr<IWindow> newWindow(std::string_view title) override {
auto newWindow = _WindowCocoaNew(title, &m_metalCtx); auto newWindow = _WindowCocoaNew(title, &m_metalCtx);
m_windows[newWindow->getPlatformHandle()] = newWindow; m_windows[newWindow->getPlatformHandle()] = newWindow;
return newWindow; return newWindow;

View File

@ -9,8 +9,9 @@
#include <Metal/Metal.h> #include <Metal/Metal.h>
#include <QuartzCore/CAMetalLayer.h> #include <QuartzCore/CAMetalLayer.h>
#include <unordered_map>
#include <mutex> #include <mutex>
#include <unordered_map>
namespace boo { namespace boo {
class IWindow; class IWindow;

View File

@ -1,12 +1,19 @@
#include "boo/graphicsdev/Metal.hpp" #include "boo/graphicsdev/Metal.hpp"
#include "CocoaCommon.hpp"
#include "boo/IApplication.hpp"
#include "boo/IGraphicsContext.hpp"
#include "boo/IWindow.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "lib/mac/CocoaCommon.hpp"
#include <condition_variable>
#include <memory>
#include <mutex>
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#import <CoreVideo/CVDisplayLink.h> #import <CoreVideo/CVDisplayLink.h>
#include "boo/IApplication.hpp"
#include "boo/IWindow.hpp" #include <logvisor/logvisor.hpp>
#include "boo/IGraphicsContext.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "logvisor/logvisor.hpp"
#if !__has_feature(objc_arc) #if !__has_feature(objc_arc)
#error ARC Required #error ARC Required
@ -93,7 +100,7 @@ static const NSOpenGLPixelFormatAttribute PF_RGBAF32_Z24_ATTRS[] =
static const NSOpenGLPixelFormatAttribute* PF_TABLE[] = static const NSOpenGLPixelFormatAttribute* PF_TABLE[] =
{ {
NULL, nullptr,
PF_RGBA8_ATTRS, PF_RGBA8_ATTRS,
PF_RGBA16_ATTRS, PF_RGBA16_ATTRS,
PF_RGBA8_Z24_ATTRS, PF_RGBA8_Z24_ATTRS,
@ -139,7 +146,7 @@ protected:
} }
public: public:
~GraphicsContextCocoa() { ~GraphicsContextCocoa() override {
if (m_dispLink) { if (m_dispLink) {
CVDisplayLinkStop(m_dispLink); CVDisplayLinkStop(m_dispLink);
CVDisplayLinkRelease(m_dispLink); CVDisplayLinkRelease(m_dispLink);
@ -223,36 +230,36 @@ public:
m_dataFactory = _NewGLDataFactory(this, glCtx); m_dataFactory = _NewGLDataFactory(this, glCtx);
} }
~GraphicsContextCocoaGL() ~GraphicsContextCocoaGL() override
{ {
m_commandQueue->stopRenderer(); m_commandQueue->stopRenderer();
fmt::print(fmt("CONTEXT DESTROYED\n")); fmt::print(fmt("CONTEXT DESTROYED\n"));
} }
void _setCallback(IWindowCallback* cb) void _setCallback(IWindowCallback* cb) override
{ {
std::lock_guard<std::recursive_mutex> lk(m_callbackMutex); std::lock_guard<std::recursive_mutex> lk(m_callbackMutex);
m_callback = cb; m_callback = cb;
} }
EGraphicsAPI getAPI() const EGraphicsAPI getAPI() const override
{ {
return m_api; return m_api;
} }
EPixelFormat getPixelFormat() const EPixelFormat getPixelFormat() const override
{ {
return m_pf; return m_pf;
} }
void setPixelFormat(EPixelFormat pf) void setPixelFormat(EPixelFormat pf) override
{ {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) bool initializeContext(void*) override
{ {
m_nsContext = [[GraphicsContextCocoaGLInternal alloc] initWithBooContext:this]; m_nsContext = [[GraphicsContextCocoaGLInternal alloc] initWithBooContext:this];
if (!m_nsContext) if (!m_nsContext)
@ -266,26 +273,26 @@ public:
return true; return true;
} }
void makeCurrent() void makeCurrent() override
{ {
[[m_nsContext openGLContext] makeCurrentContext]; [[m_nsContext openGLContext] makeCurrentContext];
} }
void postInit() void postInit() override
{ {
} }
IGraphicsCommandQueue* getCommandQueue() IGraphicsCommandQueue* getCommandQueue() override
{ {
return m_commandQueue.get(); return m_commandQueue.get();
} }
IGraphicsDataFactory* getDataFactory() IGraphicsDataFactory* getDataFactory() override
{ {
return m_dataFactory.get(); return m_dataFactory.get();
} }
IGraphicsDataFactory* getMainContextDataFactory() IGraphicsDataFactory* getMainContextDataFactory() override
{ {
if (!m_mainCtx) if (!m_mainCtx)
{ {
@ -298,7 +305,7 @@ public:
return m_dataFactory.get(); return m_dataFactory.get();
} }
IGraphicsDataFactory* getLoadContextDataFactory() IGraphicsDataFactory* getLoadContextDataFactory() override
{ {
if (!m_loadCtx) if (!m_loadCtx)
{ {
@ -311,12 +318,12 @@ public:
return m_dataFactory.get(); return m_dataFactory.get();
} }
void present() void present() override
{ {
[[m_nsContext openGLContext] flushBuffer]; [[m_nsContext openGLContext] flushBuffer];
} }
BooCocoaResponder* responder() const BooCocoaResponder* responder() const override
{ {
if (!m_nsContext) if (!m_nsContext)
return nullptr; return nullptr;
@ -330,15 +337,15 @@ IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
GLContext* glCtx) GLContext* glCtx)
{ {
if (api != IGraphicsContext::EGraphicsAPI::OpenGL3_3 && api != IGraphicsContext::EGraphicsAPI::OpenGL4_2) if (api != IGraphicsContext::EGraphicsAPI::OpenGL3_3 && api != IGraphicsContext::EGraphicsAPI::OpenGL4_2)
return NULL; return nullptr;
/* Create temporary context to query GL version */ /* Create temporary context to query GL version */
NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS]; NSOpenGLPixelFormat* nspf = [[NSOpenGLPixelFormat alloc] initWithAttributes:PF_RGBA8_ATTRS];
if (!nspf) if (!nspf)
return NULL; return nullptr;
NSOpenGLContext* nsctx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:nil]; NSOpenGLContext* nsctx = [[NSOpenGLContext alloc] initWithFormat:nspf shareContext:nil];
if (!nsctx) if (!nsctx)
return NULL; return nullptr;
[nsctx makeCurrentContext]; [nsctx makeCurrentContext];
const char* glVersion = (char*)glGetString(GL_VERSION); const char* glVersion = (char*)glGetString(GL_VERSION);
unsigned major = 0; unsigned major = 0;
@ -352,13 +359,13 @@ IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
Log.report(logvisor::Fatal, fmt("glewInit failed")); Log.report(logvisor::Fatal, fmt("glewInit failed"));
[NSOpenGLContext clearCurrentContext]; [NSOpenGLContext clearCurrentContext];
if (!glVersion) if (!glVersion)
return NULL; return nullptr;
if (major > 4 || (major == 4 && minor >= 2)) if (major > 4 || (major == 4 && minor >= 2))
api = IGraphicsContext::EGraphicsAPI::OpenGL4_2; api = IGraphicsContext::EGraphicsAPI::OpenGL4_2;
else if (major == 3 && minor >= 3) else if (major == 3 && minor >= 3)
if (api == IGraphicsContext::EGraphicsAPI::OpenGL4_2) if (api == IGraphicsContext::EGraphicsAPI::OpenGL4_2)
return NULL; return nullptr;
return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx, glCtx); return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx, glCtx);
} }
@ -384,31 +391,31 @@ public:
m_dataFactory = _NewMetalDataFactory(this, metalCtx); m_dataFactory = _NewMetalDataFactory(this, metalCtx);
} }
~GraphicsContextCocoaMetal() { ~GraphicsContextCocoaMetal() override {
m_commandQueue->stopRenderer(); m_commandQueue->stopRenderer();
m_metalCtx->m_windows.erase(m_parentWindow); m_metalCtx->m_windows.erase(m_parentWindow);
} }
void _setCallback(IWindowCallback* cb) { void _setCallback(IWindowCallback* cb) override {
std::lock_guard<std::recursive_mutex> lk(m_callbackMutex); std::lock_guard<std::recursive_mutex> lk(m_callbackMutex);
m_callback = cb; m_callback = cb;
} }
EGraphicsAPI getAPI() const { EGraphicsAPI getAPI() const override {
return m_api; return m_api;
} }
EPixelFormat getPixelFormat() const { EPixelFormat getPixelFormat() const override {
return m_pf; return m_pf;
} }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) { bool initializeContext(void*) override {
MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow]; MetalContext::Window& w = m_metalCtx->m_windows[m_parentWindow];
m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this]; m_nsContext = [[GraphicsContextCocoaMetalInternal alloc] initWithBooContext:this];
if (!m_nsContext) if (!m_nsContext)
@ -423,32 +430,32 @@ public:
return true; return true;
} }
void makeCurrent() { void makeCurrent() override {
} }
void postInit() { void postInit() override {
} }
IGraphicsCommandQueue* getCommandQueue() { IGraphicsCommandQueue* getCommandQueue() override {
return m_commandQueue.get(); return m_commandQueue.get();
} }
IGraphicsDataFactory* getDataFactory() { IGraphicsDataFactory* getDataFactory() override {
return m_dataFactory.get(); return m_dataFactory.get();
} }
IGraphicsDataFactory* getMainContextDataFactory() { IGraphicsDataFactory* getMainContextDataFactory() override {
return m_dataFactory.get(); return m_dataFactory.get();
} }
IGraphicsDataFactory* getLoadContextDataFactory() { IGraphicsDataFactory* getLoadContextDataFactory() override {
return m_dataFactory.get(); return m_dataFactory.get();
} }
void present() { void present() override {
} }
BooCocoaResponder* responder() const { BooCocoaResponder* responder() const override {
if (!m_nsContext) if (!m_nsContext)
return nullptr; return nullptr;
return m_nsContext->resp; return m_nsContext->resp;
@ -1252,47 +1259,47 @@ public:
m_nsWindow = nullptr; m_nsWindow = nullptr;
} }
~WindowCocoa() { ~WindowCocoa() override {
APP->_deletedWindow(this); APP->_deletedWindow(this);
} }
void setCallback(IWindowCallback* cb) { void setCallback(IWindowCallback* cb) override {
m_gfxCtx->_setCallback(cb); m_gfxCtx->_setCallback(cb);
} }
void closeWindow() { void closeWindow() override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
[m_nsWindow close]; [m_nsWindow close];
}); });
} }
void showWindow() { void showWindow() override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
[m_nsWindow makeKeyAndOrderFront:nil]; [m_nsWindow makeKeyAndOrderFront:nil];
}); });
} }
void hideWindow() { void hideWindow() override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
[m_nsWindow orderOut:nil]; [m_nsWindow orderOut:nil];
}); });
} }
std::string getTitle() { std::string getTitle() override {
return [[m_nsWindow title] UTF8String]; return [[m_nsWindow title] UTF8String];
} }
void setTitle(std::string_view title) { void setTitle(std::string_view title) override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
[m_nsWindow setTitle:[NSString stringWithUTF8String:title.data()]]; [m_nsWindow setTitle:[NSString stringWithUTF8String:title.data()]];
}); });
} }
void setCursor(EMouseCursor cursor) { void setCursor(EMouseCursor cursor) override {
if (cursor == m_cursor) if (cursor == m_cursor)
return; return;
m_cursor = cursor; m_cursor = cursor;
@ -1320,14 +1327,14 @@ public:
}); });
} }
void setWaitCursor(bool wait) {} void setWaitCursor(bool wait) override {}
double getWindowRefreshRate() const { double getWindowRefreshRate() const override {
/* TODO: Actually get refresh rate */ /* TODO: Actually get refresh rate */
return 60.0; return 60.0;
} }
void setWindowFrameDefault() { void setWindowFrameDefault() override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
NSScreen* mainScreen = [NSScreen mainScreen]; NSScreen* mainScreen = [NSScreen mainScreen];
@ -1338,7 +1345,7 @@ public:
}); });
} }
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const override {
NSView* view = [m_nsWindow contentView]; NSView* view = [m_nsWindow contentView];
NSRect wFrame = [view convertRectToBacking:view.frame]; NSRect wFrame = [view convertRectToBacking:view.frame];
xOut = wFrame.origin.x; xOut = wFrame.origin.x;
@ -1347,7 +1354,7 @@ public:
hOut = wFrame.size.height; hOut = wFrame.size.height;
} }
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const { void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const override {
NSView* view = [m_nsWindow contentView]; NSView* view = [m_nsWindow contentView];
NSRect wFrame = [view convertRectToBacking:view.frame]; NSRect wFrame = [view convertRectToBacking:view.frame];
xOut = wFrame.origin.x; xOut = wFrame.origin.x;
@ -1356,7 +1363,7 @@ public:
hOut = wFrame.size.height; hOut = wFrame.size.height;
} }
void setWindowFrame(float x, float y, float w, float h) { void setWindowFrame(float x, float y, float w, float h) override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
[m_nsWindow setContentSize:NSMakeSize(w, h)]; [m_nsWindow setContentSize:NSMakeSize(w, h)];
@ -1364,7 +1371,7 @@ public:
}); });
} }
void setWindowFrame(int x, int y, int w, int h) { void setWindowFrame(int x, int y, int w, int h) override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
[m_nsWindow setContentSize:NSMakeSize(w, h)]; [m_nsWindow setContentSize:NSMakeSize(w, h)];
@ -1372,15 +1379,15 @@ public:
}); });
} }
float getVirtualPixelFactor() const { float getVirtualPixelFactor() const override {
return [m_nsWindow backingScaleFactor]; return [m_nsWindow backingScaleFactor];
} }
bool isFullscreen() const { bool isFullscreen() const override {
return ([m_nsWindow styleMask] & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; return ([m_nsWindow styleMask] & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
} }
void setFullscreen(bool fs) { void setFullscreen(bool fs) override {
if ((fs && !isFullscreen()) || (!fs && isFullscreen())) if ((fs && !isFullscreen()) || (!fs && isFullscreen()))
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
@ -1388,7 +1395,7 @@ public:
}); });
} }
void claimKeyboardFocus(const int coord[2]) { void claimKeyboardFocus(const int coord[2]) override {
BooCocoaResponder* resp = m_gfxCtx->responder(); BooCocoaResponder* resp = m_gfxCtx->responder();
if (resp) { if (resp) {
dispatch_async(dispatch_get_main_queue(), dispatch_async(dispatch_get_main_queue(),
@ -1401,7 +1408,7 @@ public:
} }
} }
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) { bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) override {
NSPasteboard* pb = [NSPasteboard generalPasteboard]; NSPasteboard* pb = [NSPasteboard generalPasteboard];
[pb clearContents]; [pb clearContents];
NSData* d = [NSData dataWithBytes:data length:sz]; NSData* d = [NSData dataWithBytes:data length:sz];
@ -1409,7 +1416,7 @@ public:
return true; return true;
} }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) override {
NSPasteboard* pb = [NSPasteboard generalPasteboard]; NSPasteboard* pb = [NSPasteboard generalPasteboard];
NSData* d = [pb dataForType:ClipboardTypes[int(type)]]; NSData* d = [pb dataForType:ClipboardTypes[int(type)]];
if (!d) if (!d)
@ -1420,11 +1427,11 @@ public:
return ret; return ret;
} }
ETouchType getTouchType() const { ETouchType getTouchType() const override {
return ETouchType::Trackpad; return ETouchType::Trackpad;
} }
void setStyle(EWindowStyle style) { void setStyle(EWindowStyle style) override {
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
if ((style & EWindowStyle::Titlebar) != EWindowStyle::None) if ((style & EWindowStyle::Titlebar) != EWindowStyle::None)
m_nsWindow.titleVisibility = NSWindowTitleVisible; m_nsWindow.titleVisibility = NSWindowTitleVisible;
@ -1443,7 +1450,7 @@ public:
m_nsWindow.styleMask &= ~NSWindowStyleMaskResizable; m_nsWindow.styleMask &= ~NSWindowStyleMaskResizable;
} }
EWindowStyle getStyle() const { EWindowStyle getStyle() const override {
EWindowStyle retval = EWindowStyle::None; EWindowStyle retval = EWindowStyle::None;
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
retval |= m_nsWindow.titleVisibility == NSWindowTitleVisible ? EWindowStyle::Titlebar : EWindowStyle::None; retval |= m_nsWindow.titleVisibility == NSWindowTitleVisible ? EWindowStyle::Titlebar : EWindowStyle::None;
@ -1455,34 +1462,34 @@ public:
return retval; return retval;
} }
void setTouchBarProvider(void* provider) { void setTouchBarProvider(void* provider) override {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
[m_nsWindow setTouchBarProvider:(__bridge_transfer id) provider]; [m_nsWindow setTouchBarProvider:(__bridge_transfer id) provider];
}); });
} }
int waitForRetrace() { int waitForRetrace() override {
return static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace(); return static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace();
} }
uintptr_t getPlatformHandle() const { uintptr_t getPlatformHandle() const override {
return (uintptr_t) m_nsWindow; return (uintptr_t) m_nsWindow;
} }
IGraphicsCommandQueue* getCommandQueue() { IGraphicsCommandQueue* getCommandQueue() override {
return m_gfxCtx->getCommandQueue(); return m_gfxCtx->getCommandQueue();
} }
IGraphicsDataFactory* getDataFactory() { IGraphicsDataFactory* getDataFactory() override {
return m_gfxCtx->getDataFactory(); return m_gfxCtx->getDataFactory();
} }
IGraphicsDataFactory* getMainContextDataFactory() { IGraphicsDataFactory* getMainContextDataFactory() override {
return m_gfxCtx->getMainContextDataFactory(); return m_gfxCtx->getMainContextDataFactory();
} }
IGraphicsDataFactory* getLoadContextDataFactory() { IGraphicsDataFactory* getLoadContextDataFactory() override {
return m_gfxCtx->getLoadContextDataFactory(); return m_gfxCtx->getLoadContextDataFactory();
} }

View File

@ -1,9 +1,13 @@
#include "boo/IApplication.hpp"
#include "logvisor/logvisor.hpp"
#include "nxstl/thread" #include "nxstl/thread"
#include "nxstl/condition_variable" #include "nxstl/condition_variable"
#include "nxstl/mutex"
#include "boo/IApplication.hpp"
#include "boo/graphicsdev/NX.hpp" #include "boo/graphicsdev/NX.hpp"
#include <limits.h>
#include <climits>
#include <logvisor/logvisor.hpp>
#include <switch.h> #include <switch.h>
@ -21,7 +25,7 @@ class ApplicationNX : public IApplication {
NXContext m_nxCtx; NXContext m_nxCtx;
void _deletedWindow(IWindow* window) {} void _deletedWindow(IWindow* window) override {}
public: public:
ApplicationNX(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName, ApplicationNX(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
@ -29,9 +33,9 @@ public:
uint32_t anisotropy, bool deepColor, bool singleInstance) uint32_t anisotropy, bool deepColor, bool singleInstance)
: m_callback(callback), m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), m_args(args) {} : m_callback(callback), m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), m_args(args) {}
EPlatformType getPlatformType() const { return EPlatformType::NX; } EPlatformType getPlatformType() const override { return EPlatformType::NX; }
int run() { int run() override {
/* Spawn client thread */ /* Spawn client thread */
int clientReturn = INT_MIN; int clientReturn = INT_MIN;
std::mutex initmt; std::mutex initmt;
@ -63,16 +67,16 @@ public:
return 0; return 0;
} }
std::string_view getUniqueName() const { return m_uniqueName; } std::string_view getUniqueName() const override { return m_uniqueName; }
std::string_view getFriendlyName() const { return m_friendlyName; } std::string_view getFriendlyName() const override { return m_friendlyName; }
std::string_view getProcessName() const { return m_pname; } std::string_view getProcessName() const override { return m_pname; }
const std::vector<std::string>& getArgs() const { return m_args; } const std::vector<std::string>& getArgs() const override { return m_args; }
std::shared_ptr<IWindow> m_window; std::shared_ptr<IWindow> m_window;
std::shared_ptr<IWindow> newWindow(std::string_view title) { std::shared_ptr<IWindow> newWindow(std::string_view title) override {
if (m_window) if (m_window)
Log.report(logvisor::Fatal, fmt("Only 1 window allowed on NX")); Log.report(logvisor::Fatal, fmt("Only 1 window allowed on NX"));
m_window = _WindowNXNew(title, &m_nxCtx); m_window = _WindowNXNew(title, &m_nxCtx);

View File

@ -1,8 +1,9 @@
#include "boo/IWindow.hpp" #include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include "logvisor/logvisor.hpp"
#include "boo/graphicsdev/NX.hpp" #include "boo/graphicsdev/NX.hpp"
#include <logvisor/logvisor.hpp>
#include <switch.h> #include <switch.h>
namespace boo { namespace boo {
@ -21,18 +22,18 @@ public:
m_commandQueue = _NewNXCommandQueue(nxCtx, this); m_commandQueue = _NewNXCommandQueue(nxCtx, this);
} }
EGraphicsAPI getAPI() const { return EGraphicsAPI::NX; } EGraphicsAPI getAPI() const override { return EGraphicsAPI::NX; }
EPixelFormat getPixelFormat() const { return EPixelFormat::RGBA8; } EPixelFormat getPixelFormat() const override { return EPixelFormat::RGBA8; }
void setPixelFormat(EPixelFormat pf) {} void setPixelFormat(EPixelFormat pf) override {}
bool initializeContext(void* handle) { return m_nxCtx->initialize(); } bool initializeContext(void* handle) override { return m_nxCtx->initialize(); }
void makeCurrent() {} void makeCurrent() override {}
void postInit() {} void postInit() override {}
void present() {} void present() override {}
IGraphicsCommandQueue* getCommandQueue() { return m_commandQueue.get(); } IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue.get(); }
IGraphicsDataFactory* getDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getMainContextDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getMainContextDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getLoadContextDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_dataFactory.get(); }
}; };
class WindowNX : public IWindow { class WindowNX : public IWindow {
@ -45,20 +46,20 @@ public:
m_gfxCtx->initializeContext(nullptr); m_gfxCtx->initializeContext(nullptr);
} }
void setCallback(IWindowCallback* cb) { m_callback = cb; } void setCallback(IWindowCallback* cb) override { m_callback = cb; }
void closeWindow() {} void closeWindow() override {}
void showWindow() {} void showWindow() override {}
void hideWindow() {} void hideWindow() override {}
SystemString getTitle() { return m_title; } SystemString getTitle() override { return m_title; }
void setTitle(SystemStringView title) { m_title = title; } void setTitle(SystemStringView title) override { m_title = title; }
void setCursor(EMouseCursor cursor) {} void setCursor(EMouseCursor cursor) override {}
void setWaitCursor(bool wait) {} void setWaitCursor(bool wait) override {}
void setWindowFrameDefault() {} void setWindowFrameDefault() override {}
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const override {
u32 width, height; u32 width, height;
gfxGetFramebufferResolution(&width, &height); gfxGetFramebufferResolution(&width, &height);
xOut = 0; xOut = 0;
@ -66,7 +67,7 @@ public:
wOut = width; wOut = width;
hOut = height; hOut = height;
} }
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const { void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const override {
u32 width, height; u32 width, height;
gfxGetFramebufferResolution(&width, &height); gfxGetFramebufferResolution(&width, &height);
xOut = 0; xOut = 0;
@ -74,37 +75,37 @@ public:
wOut = width; wOut = width;
hOut = height; hOut = height;
} }
void setWindowFrame(float x, float y, float w, float h) {} void setWindowFrame(float x, float y, float w, float h) override {}
void setWindowFrame(int x, int y, int w, int h) {} void setWindowFrame(int x, int y, int w, int h) override {}
float getVirtualPixelFactor() const { return 1.f; } float getVirtualPixelFactor() const override { return 1.f; }
bool isFullscreen() const { return true; } bool isFullscreen() const override { return true; }
void setFullscreen(bool fs) {} void setFullscreen(bool fs) override {}
void claimKeyboardFocus(const int coord[2]) {} void claimKeyboardFocus(const int coord[2]) override {}
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) { return false; } bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) override { return false; }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return {}; } std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) override { return {}; }
void waitForRetrace() {} void waitForRetrace() override {}
uintptr_t getPlatformHandle() const { return 0; } uintptr_t getPlatformHandle() const override { return 0; }
bool _incomingEvent(void* event) { bool _incomingEvent(void* event) override {
(void)event; (void)event;
return false; return false;
} }
void _cleanup() {} void _cleanup() override {}
ETouchType getTouchType() const { return ETouchType::Display; } ETouchType getTouchType() const override { return ETouchType::Display; }
void setStyle(EWindowStyle style) {} void setStyle(EWindowStyle style) override {}
EWindowStyle getStyle() const { return EWindowStyle::None; } EWindowStyle getStyle() const override { return EWindowStyle::None; }
void setTouchBarProvider(void*) {} void setTouchBarProvider(void*) override {}
IGraphicsCommandQueue* getCommandQueue() { return m_gfxCtx->getCommandQueue(); } IGraphicsCommandQueue* getCommandQueue() override { return m_gfxCtx->getCommandQueue(); }
IGraphicsDataFactory* getDataFactory() { return m_gfxCtx->getDataFactory(); } IGraphicsDataFactory* getDataFactory() override { return m_gfxCtx->getDataFactory(); }
IGraphicsDataFactory* getMainContextDataFactory() { return m_gfxCtx->getMainContextDataFactory(); } IGraphicsDataFactory* getMainContextDataFactory() override { return m_gfxCtx->getMainContextDataFactory(); }
IGraphicsDataFactory* getLoadContextDataFactory() { return m_gfxCtx->getLoadContextDataFactory(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_gfxCtx->getLoadContextDataFactory(); }
}; };
std::shared_ptr<IWindow> _WindowNXNew(std::string_view title, NXContext* nxCtx) { std::shared_ptr<IWindow> _WindowNXNew(std::string_view title, NXContext* nxCtx) {

View File

@ -1,4 +1,4 @@
#include "UWPCommon.hpp" #include "lib/win/UWPCommon.hpp"
using namespace Windows::Foundation; using namespace Windows::Foundation;
using namespace Windows::UI::Core; using namespace Windows::UI::Core;
@ -12,12 +12,15 @@ using namespace Platform;
#define D3D11_CREATE_DEVICE_FLAGS 0 #define D3D11_CREATE_DEVICE_FLAGS 0
#endif #endif
#include "boo/System.hpp" #include <cstdlib>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/inputdev/DeviceFinder.hpp" #include "boo/System.hpp"
#include "boo/graphicsdev/D3D.hpp"
#include "logvisor/logvisor.hpp"
#include "boo/UWPViewProvider.hpp" #include "boo/UWPViewProvider.hpp"
#include "boo/graphicsdev/D3D.hpp"
#include "boo/inputdev/DeviceFinder.hpp"
#include <logvisor/logvisor.hpp>
#if _WIN32_WINNT_WIN10 #if _WIN32_WINNT_WIN10
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignaturePROC = nullptr; PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignaturePROC = nullptr;
@ -49,7 +52,7 @@ class ApplicationUWP final : public IApplication {
Boo3DAppContextUWP m_3dCtx; Boo3DAppContextUWP m_3dCtx;
void _deletedWindow(IWindow* window) {} void _deletedWindow(IWindow* window) override {}
public: public:
ApplicationUWP(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName, ApplicationUWP(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName,
@ -60,7 +63,7 @@ public:
, m_pname(pname) , m_pname(pname)
, m_args(args) , m_args(args)
, m_singleInstance(singleInstance) { , m_singleInstance(singleInstance) {
typedef HRESULT(WINAPI * CreateDXGIFactory1PROC)(REFIID riid, _COM_Outptr_ void** ppFactory); using CreateDXGIFactory1PROC = HRESULT (WINAPI *)(REFIID riid, _COM_Outptr_ void** ppFactory);
CreateDXGIFactory1PROC MyCreateDXGIFactory1 = CreateDXGIFactory1; CreateDXGIFactory1PROC MyCreateDXGIFactory1 = CreateDXGIFactory1;
bool no12 = true; bool no12 = true;
@ -180,10 +183,10 @@ public:
Log.report(logvisor::Fatal, fmt("system doesn't support D3D11 or D3D12")); Log.report(logvisor::Fatal, fmt("system doesn't support D3D11 or D3D12"));
} }
EPlatformType getPlatformType() const { return EPlatformType::UWP; } EPlatformType getPlatformType() const override { return EPlatformType::UWP; }
std::thread m_clientThread; std::thread m_clientThread;
int run() { int run() override {
/* Spawn client thread */ /* Spawn client thread */
int clientReturn = 0; int clientReturn = 0;
m_clientThread = std::thread([&]() { m_clientThread = std::thread([&]() {
@ -203,15 +206,15 @@ public:
m_clientThread.join(); m_clientThread.join();
} }
SystemStringView getUniqueName() const { return m_uniqueName; } SystemStringView getUniqueName() const override { return m_uniqueName; }
SystemStringView getFriendlyName() const { return m_friendlyName; } SystemStringView getFriendlyName() const override { return m_friendlyName; }
SystemStringView getProcessName() const { return m_pname; } SystemStringView getProcessName() const override { return m_pname; }
const std::vector<SystemString>& getArgs() const { return m_args; } const std::vector<SystemString>& getArgs() const override { return m_args; }
std::shared_ptr<IWindow> newWindow(SystemStringView title, uint32_t sampleCount) { std::shared_ptr<IWindow> newWindow(SystemStringView title, uint32_t sampleCount) override {
if (!m_issuedWindow) { if (!m_issuedWindow) {
m_issuedWindow = true; m_issuedWindow = true;
return m_window; return m_window;
@ -222,7 +225,7 @@ public:
void _setWindow(CoreWindow ^ window) { m_window = _WindowUWPNew(m_friendlyName, m_3dCtx); } void _setWindow(CoreWindow ^ window) { m_window = _WindowUWPNew(m_friendlyName, m_3dCtx); }
}; };
IApplication* APP = NULL; IApplication* APP = nullptr;
ref class AppView sealed : public IFrameworkView { ref class AppView sealed : public IFrameworkView {
ApplicationUWP m_app; ApplicationUWP m_app;

View File

@ -1,4 +1,5 @@
#include "Win32Common.hpp" #include "lib/win/Win32Common.hpp"
#include <shellapi.h> #include <shellapi.h>
#include <initguid.h> #include <initguid.h>
#include <Usbiodef.h> #include <Usbiodef.h>
@ -15,11 +16,16 @@ PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor = nullptr;
#define D3D11_CREATE_DEVICE_FLAGS 0 #define D3D11_CREATE_DEVICE_FLAGS 0
#endif #endif
#include "boo/System.hpp" #include <condition_variable>
#include <cstdlib>
#include <mutex>
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/inputdev/DeviceFinder.hpp" #include "boo/System.hpp"
#include "boo/graphicsdev/D3D.hpp" #include "boo/graphicsdev/D3D.hpp"
#include "logvisor/logvisor.hpp" #include "boo/inputdev/DeviceFinder.hpp"
#include <logvisor/logvisor.hpp>
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
#include "boo/graphicsdev/Vulkan.hpp" #include "boo/graphicsdev/Vulkan.hpp"
@ -86,7 +92,7 @@ class ApplicationWin32 final : public IApplication {
PFN_vkGetInstanceProcAddr m_getVkProc = nullptr; PFN_vkGetInstanceProcAddr m_getVkProc = nullptr;
#endif #endif
void _deletedWindow(IWindow* window) { m_allWindows.erase(HWND(window->getPlatformHandle())); } void _deletedWindow(IWindow* window) override { m_allWindows.erase(HWND(window->getPlatformHandle())); }
public: public:
ApplicationWin32(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName, ApplicationWin32(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName,
@ -110,8 +116,8 @@ public:
if (!dxgilib) if (!dxgilib)
Log.report(logvisor::Fatal, fmt("unable to load dxgi.dll")); Log.report(logvisor::Fatal, fmt("unable to load dxgi.dll"));
typedef HRESULT(WINAPI * CreateDXGIFactory1PROC)(REFIID riid, _COM_Outptr_ void** ppFactory); using CreateDXGIFactory1PROC = HRESULT(WINAPI*)(REFIID riid, _COM_Outptr_ void** ppFactory);
CreateDXGIFactory1PROC MyCreateDXGIFactory1 = (CreateDXGIFactory1PROC)GetProcAddress(dxgilib, "CreateDXGIFactory1"); auto MyCreateDXGIFactory1 = (CreateDXGIFactory1PROC)GetProcAddress(dxgilib, "CreateDXGIFactory1");
if (!MyCreateDXGIFactory1) if (!MyCreateDXGIFactory1)
Log.report(logvisor::Fatal, fmt("unable to find CreateDXGIFactory1 in DXGI.dll\n")); Log.report(logvisor::Fatal, fmt("unable to find CreateDXGIFactory1 in DXGI.dll\n"));
@ -272,7 +278,7 @@ public:
Log.report(logvisor::Fatal, fmt("system doesn't support Vulkan, D3D11, or OpenGL")); Log.report(logvisor::Fatal, fmt("system doesn't support Vulkan, D3D11, or OpenGL"));
} }
EPlatformType getPlatformType() const { return EPlatformType::Win32; } EPlatformType getPlatformType() const override { return EPlatformType::Win32; }
LRESULT winHwndHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT winHwndHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
/* Lookup boo window instance */ /* Lookup boo window instance */
@ -340,7 +346,7 @@ public:
MONITORINFO monitor_info; MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(monitor_info); monitor_info.cbSize = sizeof(monitor_info);
GetMonitorInfo(MonitorFromWindow(win.m_hwnd, MONITOR_DEFAULTTONEAREST), &monitor_info); GetMonitorInfo(MonitorFromWindow(win.m_hwnd, MONITOR_DEFAULTTONEAREST), &monitor_info);
SetWindowPos(win.m_hwnd, NULL, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top, SetWindowPos(win.m_hwnd, nullptr, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top,
monitor_info.rcMonitor.right - monitor_info.rcMonitor.left, monitor_info.rcMonitor.right - monitor_info.rcMonitor.left,
monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top, monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
@ -350,7 +356,7 @@ public:
SetWindowLong(win.m_hwnd, GWL_STYLE, win.m_fsStyle); SetWindowLong(win.m_hwnd, GWL_STYLE, win.m_fsStyle);
SetWindowLong(win.m_hwnd, GWL_EXSTYLE, win.m_fsExStyle); SetWindowLong(win.m_hwnd, GWL_EXSTYLE, win.m_fsExStyle);
SetWindowPos(win.m_hwnd, NULL, win.m_fsRect.left, win.m_fsRect.top, win.m_fsRect.right - win.m_fsRect.left, SetWindowPos(win.m_hwnd, nullptr, win.m_fsRect.left, win.m_fsRect.top, win.m_fsRect.right - win.m_fsRect.left,
win.m_fsRect.bottom - win.m_fsRect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); win.m_fsRect.bottom - win.m_fsRect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
win.m_fs = false; win.m_fs = false;
@ -358,7 +364,7 @@ public:
g_nwcv.notify_one(); g_nwcv.notify_one();
} }
int run() { int run() override {
g_mainThreadId = GetCurrentThreadId(); g_mainThreadId = GetCurrentThreadId();
/* Spawn client thread */ /* Spawn client thread */
@ -372,8 +378,8 @@ public:
}); });
/* Pump messages */ /* Pump messages */
MSG msg = {0}; MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) { while (GetMessage(&msg, nullptr, 0, 0)) {
if (!msg.hwnd) { if (!msg.hwnd) {
/* PostThreadMessage events */ /* PostThreadMessage events */
switch (msg.message) { switch (msg.message) {
@ -424,22 +430,22 @@ public:
return clientReturn; return clientReturn;
} }
~ApplicationWin32() { ~ApplicationWin32() override {
for (auto& p : m_allWindows) for (auto& p : m_allWindows)
if (auto w = p.second.lock()) if (auto w = p.second.lock())
w->_cleanup(); w->_cleanup();
} }
SystemStringView getUniqueName() const { return m_uniqueName; } SystemStringView getUniqueName() const override { return m_uniqueName; }
SystemStringView getFriendlyName() const { return m_friendlyName; } SystemStringView getFriendlyName() const override { return m_friendlyName; }
SystemStringView getProcessName() const { return m_pname; } SystemStringView getProcessName() const override { return m_pname; }
const std::vector<SystemString>& getArgs() const { return m_args; } const std::vector<SystemString>& getArgs() const override { return m_args; }
std::shared_ptr<IWindow> m_mwret; std::shared_ptr<IWindow> m_mwret;
std::shared_ptr<IWindow> newWindow(SystemStringView title) { std::shared_ptr<IWindow> newWindow(SystemStringView title) override {
if (GetCurrentThreadId() != g_mainThreadId) { if (GetCurrentThreadId() != g_mainThreadId) {
std::unique_lock<std::mutex> lk(g_nwmt); std::unique_lock<std::mutex> lk(g_nwmt);
if (!PostThreadMessageW(g_mainThreadId, WM_USER, WPARAM(&title), 0)) if (!PostThreadMessageW(g_mainThreadId, WM_USER, WPARAM(&title), 0))
@ -457,7 +463,7 @@ public:
} }
}; };
IApplication* APP = NULL; IApplication* APP = nullptr;
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName, int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args, SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor, std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
@ -484,7 +490,7 @@ int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& c
WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT); WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT);
/* One class for *all* boo windows */ /* One class for *all* boo windows */
WNDCLASS wndClass = {0, WindowProc, 0, 0, GetModuleHandle(nullptr), 0, 0, 0, 0, L"BooWindow"}; WNDCLASS wndClass = {0, WindowProc, 0, 0, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"BooWindow"};
wndClass.hIcon = LoadIconW(wndClass.hInstance, MAKEINTRESOURCEW(101)); wndClass.hIcon = LoadIconW(wndClass.hInstance, MAKEINTRESOURCEW(101));
wndClass.hCursor = WIN32_CURSORS.m_arrow; wndClass.hCursor = WIN32_CURSORS.m_arrow;
RegisterClassW(&wndClass); RegisterClassW(&wndClass);

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "WinCommon.hpp" #include "lib/win/WinCommon.hpp"
struct Boo3DAppContextUWP : Boo3DAppContext { struct Boo3DAppContextUWP : Boo3DAppContext {
bool isFullscreen(const boo::IWindow* window) { bool isFullscreen(const boo::IWindow* window) {

View File

@ -14,19 +14,22 @@
#endif #endif
#include "boo/graphicsdev/GL.hpp" #include "boo/graphicsdev/GL.hpp"
#include <condition_variable>
#include <mutex>
extern DWORD g_mainThreadId; extern DWORD g_mainThreadId;
extern std::mutex g_nwmt; extern std::mutex g_nwmt;
extern std::condition_variable g_nwcv; extern std::condition_variable g_nwcv;
#if _WIN32_WINNT_WINBLUE && !WINDOWS_STORE #if _WIN32_WINNT_WINBLUE && !WINDOWS_STORE
#include <ShellScalingApi.h> #include <ShellScalingApi.h>
typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(_In_ HMONITOR, _Out_ DEVICE_SCALE_FACTOR*); using PFN_GetScaleFactorForMonitor = HRESULT(WINAPI*)(_In_ HMONITOR, _Out_ DEVICE_SCALE_FACTOR*);
extern PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor; extern PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor;
#endif #endif
struct OGLContext { struct OGLContext {
ComPtr<IDXGIFactory1> m_dxFactory; ComPtr<IDXGIFactory1> m_dxFactory;
HGLRC m_lastContext = 0; HGLRC m_lastContext = nullptr;
struct Window { struct Window {
HWND m_hwnd; HWND m_hwnd;
HDC m_deviceContext; HDC m_deviceContext;

View File

@ -1,6 +1,10 @@
#pragma once #pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <unordered_map> #include <unordered_map>
#include "boo/IWindow.hpp" #include "boo/IWindow.hpp"
namespace boo { namespace boo {
@ -25,8 +29,8 @@ class IWindow;
#include <d3d9.h> #include <d3d9.h>
typedef int (WINAPI *pD3DPERF_BeginEvent)(D3DCOLOR col, LPCWSTR wszName); using pD3DPERF_BeginEvent = int (WINAPI*)(D3DCOLOR col, LPCWSTR wszName);
typedef int (WINAPI *pD3DPERF_EndEvent)(); using pD3DPERF_EndEvent = int (WINAPI*)();
struct D3D12Context { struct D3D12Context {
ComPtr<IDXGIFactory2> m_dxFactory; ComPtr<IDXGIFactory2> m_dxFactory;

View File

@ -1,11 +1,12 @@
#include "UWPCommon.hpp" #include "lib/win/UWPCommon.hpp"
#include "boo/IApplication.hpp"
#include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp"
#include "logvisor/logvisor.hpp"
#include "boo/graphicsdev/D3D.hpp" #include "boo/IApplication.hpp"
#include "boo/IGraphicsContext.hpp"
#include "boo/IWindow.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp" #include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "boo/graphicsdev/D3D.hpp"
#include <logvisor/logvisor.hpp>
using namespace Windows::UI; using namespace Windows::UI;
using namespace Windows::UI::Core; using namespace Windows::UI::Core;
@ -117,7 +118,7 @@ public:
} }
} }
~GraphicsContextUWPD3D() { ~GraphicsContextUWPD3D() override {
#if _WIN32_WINNT_WIN10 #if _WIN32_WINNT_WIN10
if (m_3dCtx.m_ctx12.m_dev) if (m_3dCtx.m_ctx12.m_dev)
m_3dCtx.m_ctx12.m_windows.erase(m_parentWindow); m_3dCtx.m_ctx12.m_windows.erase(m_parentWindow);
@ -126,33 +127,33 @@ public:
m_3dCtx.m_ctx11.m_windows.erase(m_parentWindow); m_3dCtx.m_ctx11.m_windows.erase(m_parentWindow);
} }
void _setCallback(IWindowCallback* cb) { m_callback = cb; } void _setCallback(IWindowCallback* cb) override { m_callback = cb; }
EGraphicsAPI getAPI() const { return m_api; } EGraphicsAPI getAPI() const override { return m_api; }
EPixelFormat getPixelFormat() const { return m_pf; } EPixelFormat getPixelFormat() const override { return m_pf; }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) { return true; } bool initializeContext(void*) override { return true; }
void makeCurrent() {} void makeCurrent() override {}
void postInit() {} void postInit() override {}
void present() {} void present() override {}
IGraphicsCommandQueue* getCommandQueue() { return m_commandQueue; } IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue; }
IGraphicsDataFactory* getDataFactory() { return m_dataFactory; } IGraphicsDataFactory* getDataFactory() override { return m_dataFactory; }
IGraphicsDataFactory* getMainContextDataFactory() { return m_dataFactory; } IGraphicsDataFactory* getMainContextDataFactory() override { return m_dataFactory; }
IGraphicsDataFactory* getLoadContextDataFactory() { return m_dataFactory; } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_dataFactory; }
}; };
static uint32_t translateKeysym(CoreWindow ^ window, VirtualKey sym, ESpecialKey& specialSym, static uint32_t translateKeysym(CoreWindow ^ window, VirtualKey sym, ESpecialKey& specialSym,
@ -304,76 +305,78 @@ public:
} }
} }
~WindowUWP() {} ~WindowUWP() override = default;
void setCallback(IWindowCallback* cb) { m_callback = cb; } void setCallback(IWindowCallback* cb) override { m_callback = cb; }
void closeWindow() { m_coreWindow->Close(); } void closeWindow() override { m_coreWindow->Close(); }
void showWindow() {} void showWindow() override {}
void hideWindow() {} void hideWindow() override {}
SystemString getTitle() { return SystemString(m_appView->Title->Data()); } SystemString getTitle() override { return SystemString(m_appView->Title->Data()); }
void setTitle(SystemStringView title) { m_appView->Title = ref new Platform::String(title.data()); } void setTitle(SystemStringView title) override { m_appView->Title = ref new Platform::String(title.data()); }
void setCursor(EMouseCursor cursor) {} void setCursor(EMouseCursor cursor) override {}
void setWaitCursor(bool wait) {} void setWaitCursor(bool wait) override {}
double getWindowRefreshRate() const { double getWindowRefreshRate() const {
/* TODO: Actually get refresh rate */ /* TODO: Actually get refresh rate */
return 60.0; return 60.0;
} }
void setWindowFrameDefault() {} void setWindowFrameDefault() override {}
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const override {
xOut = m_bounds.X * m_dispInfoDpiFactor; xOut = m_bounds.X * m_dispInfoDpiFactor;
yOut = m_bounds.Y * m_dispInfoDpiFactor; yOut = m_bounds.Y * m_dispInfoDpiFactor;
wOut = m_bounds.Width * m_dispInfoDpiFactor; wOut = m_bounds.Width * m_dispInfoDpiFactor;
hOut = m_bounds.Height * m_dispInfoDpiFactor; hOut = m_bounds.Height * m_dispInfoDpiFactor;
} }
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const { void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const override {
xOut = m_bounds.X * m_dispInfoDpiFactor; xOut = m_bounds.X * m_dispInfoDpiFactor;
yOut = m_bounds.Y * m_dispInfoDpiFactor; yOut = m_bounds.Y * m_dispInfoDpiFactor;
wOut = m_bounds.Width * m_dispInfoDpiFactor; wOut = m_bounds.Width * m_dispInfoDpiFactor;
hOut = m_bounds.Height * m_dispInfoDpiFactor; hOut = m_bounds.Height * m_dispInfoDpiFactor;
} }
void setWindowFrame(float x, float y, float w, float h) {} void setWindowFrame(float x, float y, float w, float h) override {}
void setWindowFrame(int x, int y, int w, int h) {} void setWindowFrame(int x, int y, int w, int h) override {}
float getVirtualPixelFactor() const { return m_dispInfoDpiFactor; } float getVirtualPixelFactor() const override { return m_dispInfoDpiFactor; }
bool isFullscreen() const { return ApplicationView::GetForCurrentView()->IsFullScreenMode; } bool isFullscreen() const override { return ApplicationView::GetForCurrentView()->IsFullScreenMode; }
void setFullscreen(bool fs) { void setFullscreen(bool fs) override {
if (fs) if (fs)
ApplicationView::GetForCurrentView()->TryEnterFullScreenMode(); ApplicationView::GetForCurrentView()->TryEnterFullScreenMode();
else else
ApplicationView::GetForCurrentView()->ExitFullScreenMode(); ApplicationView::GetForCurrentView()->ExitFullScreenMode();
} }
void claimKeyboardFocus(const int coord[2]) {} void claimKeyboardFocus(const int coord[2]) override {}
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) { return false; } bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) override { return false; }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return std::unique_ptr<uint8_t[]>(); } std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) override {
return std::unique_ptr<uint8_t[]>();
}
int waitForRetrace(IAudioVoiceEngine* engine) { int waitForRetrace(IAudioVoiceEngine* engine) override {
if (engine) if (engine)
engine->pumpAndMixVoices(); engine->pumpAndMixVoices();
m_gfxCtx->m_output->WaitForVBlank(); m_gfxCtx->m_output->WaitForVBlank();
return 1; return 1;
} }
uintptr_t getPlatformHandle() const { return 0; } uintptr_t getPlatformHandle() const override { return 0; }
bool _incomingEvent(void* ev) { return false; } bool _incomingEvent(void* ev) override { return false; }
void OnKeyDown(CoreWindow ^ window, KeyEventArgs ^ keyEventArgs) { void OnKeyDown(CoreWindow ^ window, KeyEventArgs ^ keyEventArgs) {
ESpecialKey specialKey; ESpecialKey specialKey;
@ -469,23 +472,23 @@ public:
m_callback->resized(rect, false); m_callback->resized(rect, false);
} }
ETouchType getTouchType() const { return ETouchType::None; } ETouchType getTouchType() const override { return ETouchType::None; }
void setStyle(EWindowStyle style) {} void setStyle(EWindowStyle style) override {}
EWindowStyle getStyle() const { EWindowStyle getStyle() const override {
EWindowStyle retval = EWindowStyle::None; EWindowStyle retval = EWindowStyle::None;
return retval; return retval;
} }
IGraphicsCommandQueue* getCommandQueue() { return m_gfxCtx->getCommandQueue(); } IGraphicsCommandQueue* getCommandQueue() override { return m_gfxCtx->getCommandQueue(); }
IGraphicsDataFactory* getDataFactory() { return m_gfxCtx->getDataFactory(); } IGraphicsDataFactory* getDataFactory() override { return m_gfxCtx->getDataFactory(); }
/* Creates a new context on current thread!! Call from main client thread */ /* Creates a new context on current thread!! Call from main client thread */
IGraphicsDataFactory* getMainContextDataFactory() { return m_gfxCtx->getMainContextDataFactory(); } IGraphicsDataFactory* getMainContextDataFactory() override { return m_gfxCtx->getMainContextDataFactory(); }
/* Creates a new context on current thread!! Call from client loading thread */ /* Creates a new context on current thread!! Call from client loading thread */
IGraphicsDataFactory* getLoadContextDataFactory() { return m_gfxCtx->getLoadContextDataFactory(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_gfxCtx->getLoadContextDataFactory(); }
}; };
std::shared_ptr<IWindow> _WindowUWPNew(SystemStringView title, Boo3DAppContextUWP& d3dCtx) { std::shared_ptr<IWindow> _WindowUWPNew(SystemStringView title, Boo3DAppContextUWP& d3dCtx) {

View File

@ -1,15 +1,16 @@
#include "Win32Common.hpp" #include "lib/win/Win32Common.hpp"
#include <Windowsx.h>
#include "boo/IApplication.hpp"
#include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp"
#include "logvisor/logvisor.hpp"
#include <Windowsx.h>
#include "boo/IApplication.hpp"
#include "boo/IGraphicsContext.hpp"
#include "boo/IWindow.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "boo/graphicsdev/D3D.hpp" #include "boo/graphicsdev/D3D.hpp"
#include "boo/graphicsdev/GL.hpp" #include "boo/graphicsdev/GL.hpp"
#include "boo/graphicsdev/glew.h" #include "boo/graphicsdev/glew.h"
#include "boo/graphicsdev/wglew.h" #include "boo/graphicsdev/wglew.h"
#include "boo/audiodev/IAudioVoiceEngine.hpp"
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
#include "boo/graphicsdev/Vulkan.hpp" #include "boo/graphicsdev/Vulkan.hpp"
@ -19,6 +20,8 @@
#include <dxgi1_5.h> #include <dxgi1_5.h>
#endif #endif
#include <logvisor/logvisor.hpp>
static const int ContextAttribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 3, static const int ContextAttribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
// WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, // WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
@ -88,35 +91,35 @@ public:
Log.report(logvisor::Fatal, fmt("unable to get DXGI output")); Log.report(logvisor::Fatal, fmt("unable to get DXGI output"));
} }
~GraphicsContextWin32D3D() { m_3dCtx.m_ctx11.m_windows.erase(m_parentWindow); } ~GraphicsContextWin32D3D() override { m_3dCtx.m_ctx11.m_windows.erase(m_parentWindow); }
void _setCallback(IWindowCallback* cb) { m_callback = cb; } void _setCallback(IWindowCallback* cb) override { m_callback = cb; }
EGraphicsAPI getAPI() const { return m_api; } EGraphicsAPI getAPI() const override { return m_api; }
EPixelFormat getPixelFormat() const { return m_pf; } EPixelFormat getPixelFormat() const override { return m_pf; }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) { return true; } bool initializeContext(void*) override { return true; }
void makeCurrent() {} void makeCurrent() override {}
void postInit() {} void postInit() override {}
void present() {} void present() override {}
IGraphicsCommandQueue* getCommandQueue() { return m_commandQueue.get(); } IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue.get(); }
IGraphicsDataFactory* getDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getMainContextDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getMainContextDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getLoadContextDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_dataFactory.get(); }
}; };
struct GraphicsContextWin32GL : GraphicsContextWin32 { struct GraphicsContextWin32GL : GraphicsContextWin32 {
@ -198,7 +201,7 @@ public:
Log.report(logvisor::Fatal, fmt("glewInit failed")); Log.report(logvisor::Fatal, fmt("glewInit failed"));
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
wglMakeCurrent(w.m_deviceContext, 0); wglMakeCurrent(w.m_deviceContext, nullptr);
wglDeleteContext(tmpCtx); wglDeleteContext(tmpCtx);
if (b3dCtx.m_ctxOgl.m_glCtx.m_deepColor) { if (b3dCtx.m_ctxOgl.m_glCtx.m_deepColor) {
@ -249,23 +252,23 @@ public:
m_commandQueue->startRenderer(); m_commandQueue->startRenderer();
} }
~GraphicsContextWin32GL() { m_3dCtx.m_ctxOgl.m_windows.erase(m_parentWindow); } ~GraphicsContextWin32GL() override { m_3dCtx.m_ctxOgl.m_windows.erase(m_parentWindow); }
void _setCallback(IWindowCallback* cb) { m_callback = cb; } void _setCallback(IWindowCallback* cb) override { m_callback = cb; }
EGraphicsAPI getAPI() const { return m_api; } EGraphicsAPI getAPI() const override { return m_api; }
EPixelFormat getPixelFormat() const { return m_pf; } EPixelFormat getPixelFormat() const override { return m_pf; }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) { return true; } bool initializeContext(void*) override { return true; }
void makeCurrent() { void makeCurrent() override {
OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow]; OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow];
// if (!wglMakeCurrent(w.m_deviceContext, w.m_mainContext)) // if (!wglMakeCurrent(w.m_deviceContext, w.m_mainContext))
// Log.report(logvisor::Fatal, fmt("unable to make WGL context current")); // Log.report(logvisor::Fatal, fmt("unable to make WGL context current"));
@ -277,7 +280,7 @@ public:
Log.report(logvisor::Fatal, fmt("unable to make WGL context current")); Log.report(logvisor::Fatal, fmt("unable to make WGL context current"));
} }
void postInit() { void postInit() override {
// OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow]; // OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow];
// wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) // wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
@ -293,18 +296,18 @@ public:
wglSwapIntervalEXT(1); wglSwapIntervalEXT(1);
} }
void present() { void present() override {
OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow]; OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow];
SwapBuffers(w.m_deviceContext); SwapBuffers(w.m_deviceContext);
} }
IGraphicsCommandQueue* getCommandQueue() { return m_commandQueue.get(); } IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue.get(); }
IGraphicsDataFactory* getDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getDataFactory() override { return m_dataFactory.get(); }
/* Creates a new context on current thread!! Call from client loading thread */ /* Creates a new context on current thread!! Call from client loading thread */
HGLRC m_mainCtx = 0; HGLRC m_mainCtx = nullptr;
IGraphicsDataFactory* getMainContextDataFactory() { IGraphicsDataFactory* getMainContextDataFactory() override {
OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow]; OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow];
if (!m_mainCtx) { if (!m_mainCtx) {
m_mainCtx = wglCreateContextAttribsARB(w.m_deviceContext, w.m_mainContext, ContextAttribs); m_mainCtx = wglCreateContextAttribsARB(w.m_deviceContext, w.m_mainContext, ContextAttribs);
@ -317,8 +320,8 @@ public:
} }
/* Creates a new context on current thread!! Call from client loading thread */ /* Creates a new context on current thread!! Call from client loading thread */
HGLRC m_loadCtx = 0; HGLRC m_loadCtx = nullptr;
IGraphicsDataFactory* getLoadContextDataFactory() { IGraphicsDataFactory* getLoadContextDataFactory() override {
OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow]; OGLContext::Window& w = m_3dCtx.m_ctxOgl.m_windows[m_parentWindow];
if (!m_loadCtx) { if (!m_loadCtx) {
m_loadCtx = wglCreateContextAttribsARB(w.m_deviceContext, w.m_mainContext, ContextAttribs); m_loadCtx = wglCreateContextAttribsARB(w.m_deviceContext, w.m_mainContext, ContextAttribs);
@ -347,8 +350,11 @@ struct GraphicsContextWin32Vulkan : GraphicsContextWin32 {
bool m_vsyncRunning; bool m_vsyncRunning;
static void ThrowIfFailed(VkResult res) { static void ThrowIfFailed(VkResult res) {
if (res != VK_SUCCESS) if (res == VK_SUCCESS) {
Log.report(logvisor::Fatal, fmt("%d\n"), res); return;
}
Log.report(logvisor::Fatal, fmt("{}\n"), res);
} }
public: public:
@ -400,7 +406,7 @@ public:
m_ctx->m_windows.erase(m_parentWindow); m_ctx->m_windows.erase(m_parentWindow);
} }
~GraphicsContextWin32Vulkan() { destroy(); } ~GraphicsContextWin32Vulkan() override { destroy(); }
VulkanContext::Window* m_windowCtx = nullptr; VulkanContext::Window* m_windowCtx = nullptr;
@ -409,19 +415,19 @@ public:
m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace, rect); m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace, rect);
} }
void _setCallback(IWindowCallback* cb) { m_callback = cb; } void _setCallback(IWindowCallback* cb) override { m_callback = cb; }
EGraphicsAPI getAPI() const { return m_api; } EGraphicsAPI getAPI() const override { return m_api; }
EPixelFormat getPixelFormat() const { return m_pf; } EPixelFormat getPixelFormat() const override { return m_pf; }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) { bool initializeContext(void*) override {
m_windowCtx = m_ctx->m_windows.emplace(std::make_pair(m_parentWindow, std::make_unique<VulkanContext::Window>())) m_windowCtx = m_ctx->m_windows.emplace(std::make_pair(m_parentWindow, std::make_unique<VulkanContext::Window>()))
.first->second.get(); .first->second.get();
m_windowCtx->m_hwnd = m_hwnd; m_windowCtx->m_hwnd = m_hwnd;
@ -509,19 +515,19 @@ public:
return true; return true;
} }
void makeCurrent() {} void makeCurrent() override {}
void postInit() {} void postInit() override {}
IGraphicsCommandQueue* getCommandQueue() { return m_commandQueue.get(); } IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue.get(); }
IGraphicsDataFactory* getDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getMainContextDataFactory() { return getDataFactory(); } IGraphicsDataFactory* getMainContextDataFactory() override { return getDataFactory(); }
IGraphicsDataFactory* getLoadContextDataFactory() { return getDataFactory(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return getDataFactory(); }
void present() {} void present() override {}
}; };
#endif #endif
@ -852,7 +858,7 @@ public:
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE); AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);
m_hwnd = CreateWindowW(L"BooWindow", title.data(), WS_OVERLAPPEDWINDOW, r.left, r.top, r.right - r.left, m_hwnd = CreateWindowW(L"BooWindow", title.data(), WS_OVERLAPPEDWINDOW, r.left, r.top, r.right - r.left,
r.bottom - r.top, NULL, NULL, NULL, NULL); r.bottom - r.top, nullptr, nullptr, nullptr, nullptr);
HINSTANCE wndInstance = HINSTANCE(GetWindowLongPtr(m_hwnd, GWLP_HINSTANCE)); HINSTANCE wndInstance = HINSTANCE(GetWindowLongPtr(m_hwnd, GWLP_HINSTANCE));
m_imc = ImmGetContext(m_hwnd); m_imc = ImmGetContext(m_hwnd);
@ -874,37 +880,37 @@ public:
m_gfxCtx.reset(new GraphicsContextWin32D3D(api, this, m_hwnd, b3dCtx)); m_gfxCtx.reset(new GraphicsContextWin32D3D(api, this, m_hwnd, b3dCtx));
} }
void _cleanup() { m_gfxCtx.reset(); } void _cleanup() override { m_gfxCtx.reset(); }
void setCallback(IWindowCallback* cb) { m_callback = cb; } void setCallback(IWindowCallback* cb) override { m_callback = cb; }
void closeWindow() { void closeWindow() override {
// TODO: Perform thread-coalesced deallocation // TODO: Perform thread-coalesced deallocation
ShowWindow(m_hwnd, SW_HIDE); ShowWindow(m_hwnd, SW_HIDE);
} }
void showWindow() { ShowWindow(m_hwnd, SW_SHOW); } void showWindow() override { ShowWindow(m_hwnd, SW_SHOW); }
void hideWindow() { ShowWindow(m_hwnd, SW_HIDE); } void hideWindow() override { ShowWindow(m_hwnd, SW_HIDE); }
SystemString getTitle() { SystemString getTitle() override {
wchar_t title[256]; wchar_t title[256];
int c = GetWindowTextW(m_hwnd, title, 256); int c = GetWindowTextW(m_hwnd, title, 256);
return SystemString(title, c); return SystemString(title, c);
} }
void setTitle(SystemStringView title) { SetWindowTextW(m_hwnd, title.data()); } void setTitle(SystemStringView title) override { SetWindowTextW(m_hwnd, title.data()); }
static void _setCursor(HCURSOR cur) { PostThreadMessageW(g_mainThreadId, WM_USER + 2, WPARAM(cur), 0); } static void _setCursor(HCURSOR cur) { PostThreadMessageW(g_mainThreadId, WM_USER + 2, WPARAM(cur), 0); }
void setCursor(EMouseCursor cursor) { void setCursor(EMouseCursor cursor) override {
if (cursor == m_cursor && !m_cursorWait) if (cursor == m_cursor && !m_cursorWait)
return; return;
m_cursor = cursor; m_cursor = cursor;
_setCursor(GetWin32Cursor(cursor)); _setCursor(GetWin32Cursor(cursor));
} }
void setWaitCursor(bool wait) { void setWaitCursor(bool wait) override {
if (wait && !m_cursorWait) { if (wait && !m_cursorWait) {
_setCursor(WIN32_CURSORS.m_wait); _setCursor(WIN32_CURSORS.m_wait);
m_cursorWait = true; m_cursorWait = true;
@ -914,12 +920,12 @@ public:
} }
} }
double getWindowRefreshRate() const { double getWindowRefreshRate() const override {
/* TODO: Actually get refresh rate */ /* TODO: Actually get refresh rate */
return 60.0; return 60.0;
} }
void setWindowFrameDefault() { void setWindowFrameDefault() override {
MONITORINFO monInfo = {}; MONITORINFO monInfo = {};
monInfo.cbSize = sizeof(MONITORINFO); monInfo.cbSize = sizeof(MONITORINFO);
HMONITOR mon = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTOPRIMARY); HMONITOR mon = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTOPRIMARY);
@ -929,7 +935,7 @@ public:
setWindowFrame(x, y, w, h); setWindowFrame(x, y, w, h);
} }
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const override {
RECT rct; RECT rct;
GetClientRect(m_hwnd, &rct); GetClientRect(m_hwnd, &rct);
POINT pt; POINT pt;
@ -942,7 +948,7 @@ public:
hOut = rct.bottom; hOut = rct.bottom;
} }
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const { void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const override {
RECT rct; RECT rct;
GetClientRect(m_hwnd, &rct); GetClientRect(m_hwnd, &rct);
POINT pt; POINT pt;
@ -955,15 +961,15 @@ public:
hOut = rct.bottom; hOut = rct.bottom;
} }
void setWindowFrame(float x, float y, float w, float h) { setWindowFrame(int(x), int(y), int(w), int(h)); } void setWindowFrame(float x, float y, float w, float h) override { setWindowFrame(int(x), int(y), int(w), int(h)); }
void setWindowFrame(int x, int y, int w, int h) { void setWindowFrame(int x, int y, int w, int h) override {
RECT r = {x, y, x + w, y + h}; RECT r = {x, y, x + w, y + h};
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE); AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);
MoveWindow(m_hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, true); MoveWindow(m_hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, true);
} }
float getVirtualPixelFactor() const { float getVirtualPixelFactor() const override {
#if _WIN32_WINNT_WINBLUE #if _WIN32_WINNT_WINBLUE
if (MyGetScaleFactorForMonitor) { if (MyGetScaleFactorForMonitor) {
DEVICE_SCALE_FACTOR Factor; DEVICE_SCALE_FACTOR Factor;
@ -977,9 +983,9 @@ public:
return 1.f; return 1.f;
} }
bool isFullscreen() const { return m_gfxCtx->m_3dCtx.isFullscreen(this); } bool isFullscreen() const override { return m_gfxCtx->m_3dCtx.isFullscreen(this); }
void setFullscreen(bool fs) { m_gfxCtx->m_3dCtx.setFullscreen(this, fs); } void setFullscreen(bool fs) override { m_gfxCtx->m_3dCtx.setFullscreen(this, fs); }
void _immSetOpenStatus(bool open) { void _immSetOpenStatus(bool open) {
if (GetCurrentThreadId() != g_mainThreadId) { if (GetCurrentThreadId() != g_mainThreadId) {
@ -1005,7 +1011,7 @@ public:
ImmSetCompositionWindow(m_imc, &m_cForm); ImmSetCompositionWindow(m_imc, &m_cForm);
} }
void claimKeyboardFocus(const int coord[2]) { void claimKeyboardFocus(const int coord[2]) override {
if (!coord) { if (!coord) {
//_immSetOpenStatus(false); //_immSetOpenStatus(false);
return; return;
@ -1014,7 +1020,7 @@ public:
//_immSetOpenStatus(true); //_immSetOpenStatus(true);
} }
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) { bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) override {
switch (type) { switch (type) {
case EClipboardType::String: { case EClipboardType::String: {
HGLOBAL gStr = MakeANSICRLF(reinterpret_cast<const char*>(data), sz); HGLOBAL gStr = MakeANSICRLF(reinterpret_cast<const char*>(data), sz);
@ -1038,7 +1044,7 @@ public:
return false; return false;
} }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) override {
switch (type) { switch (type) {
case EClipboardType::String: { case EClipboardType::String: {
OpenClipboard(m_hwnd); OpenClipboard(m_hwnd);
@ -1068,9 +1074,12 @@ public:
return std::unique_ptr<uint8_t[]>(); return std::unique_ptr<uint8_t[]>();
} }
int waitForRetrace() { m_gfxCtx->m_output->WaitForVBlank(); return 1; } int waitForRetrace() override {
m_gfxCtx->m_output->WaitForVBlank();
return 1;
}
uintptr_t getPlatformHandle() const { return uintptr_t(m_hwnd); } uintptr_t getPlatformHandle() const override { return uintptr_t(m_hwnd); }
void buttonDown(HWNDEvent& e, EMouseButton button) { void buttonDown(HWNDEvent& e, EMouseButton button) {
if (m_callback) { if (m_callback) {
@ -1105,7 +1114,7 @@ public:
} }
bool mouseTracking = false; bool mouseTracking = false;
bool _incomingEvent(void* ev) { bool _incomingEvent(void* ev) override {
HWNDEvent& e = *static_cast<HWNDEvent*>(ev); HWNDEvent& e = *static_cast<HWNDEvent*>(ev);
switch (e.uMsg) { switch (e.uMsg) {
case WM_CLOSE: case WM_CLOSE:
@ -1288,9 +1297,9 @@ public:
return false; return false;
} }
ETouchType getTouchType() const { return ETouchType::None; } ETouchType getTouchType() const override { return ETouchType::None; }
void setStyle(EWindowStyle style) { void setStyle(EWindowStyle style) override {
LONG sty = GetWindowLong(m_hwnd, GWL_STYLE); LONG sty = GetWindowLong(m_hwnd, GWL_STYLE);
if ((style & EWindowStyle::Titlebar) != EWindowStyle::None) if ((style & EWindowStyle::Titlebar) != EWindowStyle::None)
@ -1311,7 +1320,7 @@ public:
SetWindowLong(m_hwnd, GWL_STYLE, sty); SetWindowLong(m_hwnd, GWL_STYLE, sty);
} }
EWindowStyle getStyle() const { EWindowStyle getStyle() const override {
LONG sty = GetWindowLong(m_hwnd, GWL_STYLE); LONG sty = GetWindowLong(m_hwnd, GWL_STYLE);
EWindowStyle retval = EWindowStyle::None; EWindowStyle retval = EWindowStyle::None;
if ((sty & WS_CAPTION) != 0) if ((sty & WS_CAPTION) != 0)
@ -1323,14 +1332,14 @@ public:
return retval; return retval;
} }
IGraphicsCommandQueue* getCommandQueue() { return m_gfxCtx->getCommandQueue(); } IGraphicsCommandQueue* getCommandQueue() override { return m_gfxCtx->getCommandQueue(); }
IGraphicsDataFactory* getDataFactory() { return m_gfxCtx->getDataFactory(); } IGraphicsDataFactory* getDataFactory() override { return m_gfxCtx->getDataFactory(); }
/* Creates a new context on current thread!! Call from main client thread */ /* Creates a new context on current thread!! Call from main client thread */
IGraphicsDataFactory* getMainContextDataFactory() { return m_gfxCtx->getMainContextDataFactory(); } IGraphicsDataFactory* getMainContextDataFactory() override { return m_gfxCtx->getMainContextDataFactory(); }
/* Creates a new context on current thread!! Call from client loading thread */ /* Creates a new context on current thread!! Call from client loading thread */
IGraphicsDataFactory* getLoadContextDataFactory() { return m_gfxCtx->getLoadContextDataFactory(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_gfxCtx->getLoadContextDataFactory(); }
}; };
std::shared_ptr<IWindow> _WindowWin32New(SystemStringView title, Boo3DAppContextWin32& d3dCtx) { std::shared_ptr<IWindow> _WindowWin32New(SystemStringView title, Boo3DAppContextWin32& d3dCtx) {

View File

@ -4,12 +4,15 @@
#define APPLICATION_UNIX_CPP #define APPLICATION_UNIX_CPP
#include <dbus/dbus.h>
#include <cstdint> #include <cstdint>
#include <unistd.h> #include <cstdlib>
#include "logvisor/logvisor.hpp"
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include <dbus/dbus.h>
#include <logvisor/logvisor.hpp>
#include <unistd.h>
namespace boo { namespace boo {
static logvisor::Module Log("boo::ApplicationUnix"); static logvisor::Module Log("boo::ApplicationUnix");
IApplication* APP = nullptr; IApplication* APP = nullptr;
@ -99,8 +102,8 @@ DBusConnection* RegisterDBus(const char* appName, bool& isFirst) {
fmt::print(stderr, fmt("DBus Connection Error ({})\n"), err.message); fmt::print(stderr, fmt("DBus Connection Error ({})\n"), err.message);
dbus_error_free(&err); dbus_error_free(&err);
} }
if (NULL == conn) if (conn == nullptr)
return NULL; return nullptr;
/* request our name on the bus and check for errors */ /* request our name on the bus and check for errors */
int ret = dbus_bus_request_name(conn, fmt::format(fmt("boo.{}.unique"), appName).c_str(), int ret = dbus_bus_request_name(conn, fmt::format(fmt("boo.{}.unique"), appName).c_str(),
@ -109,7 +112,7 @@ DBusConnection* RegisterDBus(const char* appName, bool& isFirst) {
fmt::print(stderr, fmt("DBus Name Error ({})\n"), err.message); fmt::print(stderr, fmt("DBus Name Error ({})\n"), err.message);
dbus_error_free(&err); dbus_error_free(&err);
dbus_connection_close(conn); dbus_connection_close(conn);
return NULL; return nullptr;
} }
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret)
isFirst = false; isFirst = false;

View File

@ -19,7 +19,7 @@ class ApplicationWayland final : public IApplication {
const std::vector<std::string> m_args; const std::vector<std::string> m_args;
bool m_singleInstance; bool m_singleInstance;
void _deletedWindow(IWindow* window) { (void)window; } void _deletedWindow(IWindow* window) override { (void)window; }
public: public:
ApplicationWayland(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName, ApplicationWayland(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
@ -35,19 +35,19 @@ public:
(void)m_singleInstance; (void)m_singleInstance;
} }
EPlatformType getPlatformType() const { return EPlatformType::Wayland; } EPlatformType getPlatformType() const override { return EPlatformType::Wayland; }
int run() { return 0; } int run() override { return 0; }
std::string_view getUniqueName() const { return m_uniqueName; } std::string_view getUniqueName() const override { return m_uniqueName; }
std::string_view getFriendlyName() const { return m_friendlyName; } std::string_view getFriendlyName() const override { return m_friendlyName; }
std::string_view getProcessName() const { return m_pname; } std::string_view getProcessName() const override { return m_pname; }
const std::vector<std::string>& getArgs() const { return m_args; } const std::vector<std::string>& getArgs() const override { return m_args; }
std::shared_ptr<IWindow> newWindow(std::string_view title) { return _WindowWaylandNew(title); } std::shared_ptr<IWindow> newWindow(std::string_view title) override { return _WindowWaylandNew(title); }
}; };
} // namespace boo } // namespace boo

View File

@ -4,7 +4,7 @@
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/graphicsdev/GL.hpp" #include "boo/graphicsdev/GL.hpp"
#include "../Common.hpp" #include "lib/Common.hpp"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
@ -12,16 +12,17 @@
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
#include <GL/glx.h> #include <GL/glx.h>
#include <GL/glxext.h> #include <GL/glxext.h>
#include <locale>
#include <dbus/dbus.h> #include <dbus/dbus.h>
DBusConnection* RegisterDBus(const char* appName, bool& isFirst); DBusConnection* RegisterDBus(const char* appName, bool& isFirst);
#include <signal.h> #include <clocale>
#include <condition_variable>
#include <csignal>
#include <locale>
#include <mutex>
#include <sys/param.h> #include <sys/param.h>
#include <thread> #include <thread>
#include <mutex>
#include <condition_variable>
#include "XlibCommon.hpp" #include "XlibCommon.hpp"
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
@ -196,7 +197,7 @@ class ApplicationXlib final : public IApplication {
} }
#endif #endif
void _deletedWindow(IWindow* window) { m_windows.erase((Window)window->getPlatformHandle()); } void _deletedWindow(IWindow* window) override { m_windows.erase((Window)window->getPlatformHandle()); }
public: public:
ApplicationXlib(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName, ApplicationXlib(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
@ -368,7 +369,7 @@ public:
XFlush(m_xDisp); XFlush(m_xDisp);
} }
~ApplicationXlib() { ~ApplicationXlib() override {
for (auto& p : m_windows) for (auto& p : m_windows)
if (auto w = p.second.lock()) if (auto w = p.second.lock())
w->_cleanup(); w->_cleanup();
@ -385,7 +386,7 @@ public:
XCloseDisplay(m_xDisp); XCloseDisplay(m_xDisp);
} }
EPlatformType getPlatformType() const { return EPlatformType::Xlib; } EPlatformType getPlatformType() const override { return EPlatformType::Xlib; }
/* Empty handler for SIGINT */ /* Empty handler for SIGINT */
static void _sigint(int) {} static void _sigint(int) {}
@ -414,7 +415,7 @@ public:
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} }
int run() { int run() override {
if (!m_xDisp) if (!m_xDisp)
return 1; return 1;
@ -459,7 +460,7 @@ public:
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(m_x11Fd, &fds); FD_SET(m_x11Fd, &fds);
FD_SET(m_dbusFd, &fds); FD_SET(m_dbusFd, &fds);
if (pselect(m_maxFd + 1, &fds, NULL, NULL, NULL, &origmask) < 0) { if (pselect(m_maxFd + 1, &fds, nullptr, nullptr, nullptr, &origmask) < 0) {
/* SIGINT/SIGUSR2 handled here */ /* SIGINT/SIGUSR2 handled here */
if (errno == EINTR) if (errno == EINTR)
break; break;
@ -512,15 +513,15 @@ public:
return clientReturn; return clientReturn;
} }
std::string_view getUniqueName() const { return m_uniqueName; } std::string_view getUniqueName() const override { return m_uniqueName; }
std::string_view getFriendlyName() const { return m_friendlyName; } std::string_view getFriendlyName() const override { return m_friendlyName; }
std::string_view getProcessName() const { return m_pname; } std::string_view getProcessName() const override { return m_pname; }
const std::vector<std::string>& getArgs() const { return m_args; } const std::vector<std::string>& getArgs() const override { return m_args; }
std::shared_ptr<IWindow> newWindow(std::string_view title) { std::shared_ptr<IWindow> newWindow(std::string_view title) override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, m_xcbConn, m_xDefaultScreen, m_xIM, m_bestStyle, std::shared_ptr<IWindow> newWindow = _WindowXlibNew(title, m_xDisp, m_xcbConn, m_xDefaultScreen, m_xIM, m_bestStyle,

View File

@ -1,4 +1,5 @@
#include "boo/IWindow.hpp" #include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp" #include "boo/IGraphicsContext.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp" #include "boo/audiodev/IAudioVoiceEngine.hpp"
@ -19,35 +20,35 @@ public:
GraphicsContextWayland(EGraphicsAPI api, IWindow* parentWindow) GraphicsContextWayland(EGraphicsAPI api, IWindow* parentWindow)
: m_api(api), m_pf(EPixelFormat::RGBA8), m_parentWindow(parentWindow) {} : m_api(api), m_pf(EPixelFormat::RGBA8), m_parentWindow(parentWindow) {}
~GraphicsContextWayland() {} ~GraphicsContextWayland() override = default;
void _setCallback(IWindowCallback* cb) { m_callback = cb; } void _setCallback(IWindowCallback* cb) override { m_callback = cb; }
EGraphicsAPI getAPI() const { return m_api; } EGraphicsAPI getAPI() const override { return m_api; }
EPixelFormat getPixelFormat() const { return m_pf; } EPixelFormat getPixelFormat() const override { return m_pf; }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) { return false; } bool initializeContext(void*) override { return false; }
void makeCurrent() {} void makeCurrent() override {}
void postInit() {} void postInit() override {}
IGraphicsCommandQueue* getCommandQueue() { return nullptr; } IGraphicsCommandQueue* getCommandQueue() override { return nullptr; }
IGraphicsDataFactory* getDataFactory() { return nullptr; } IGraphicsDataFactory* getDataFactory() override { return nullptr; }
IGraphicsDataFactory* getMainContextDataFactory() { return nullptr; } IGraphicsDataFactory* getMainContextDataFactory() override { return nullptr; }
IGraphicsDataFactory* getLoadContextDataFactory() { return nullptr; } IGraphicsDataFactory* getLoadContextDataFactory() override { return nullptr; }
void present() {} void present() override {}
}; };
struct WindowWayland : IWindow { struct WindowWayland : IWindow {
@ -55,65 +56,65 @@ struct WindowWayland : IWindow {
WindowWayland(std::string_view title) : m_gfxCtx(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this) {} WindowWayland(std::string_view title) : m_gfxCtx(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this) {}
~WindowWayland() {} ~WindowWayland() override = default;
void setCallback(IWindowCallback* cb) {} void setCallback(IWindowCallback* cb) override {}
void closeWindow() {} void closeWindow() override {}
void showWindow() {} void showWindow() override {}
void hideWindow() {} void hideWindow() override {}
std::string getTitle() { return ""; } std::string getTitle() override { return ""; }
void setTitle(std::string_view title) {} void setTitle(std::string_view title) override {}
void setCursor(EMouseCursor cursor) {} void setCursor(EMouseCursor cursor) override {}
void setWaitCursor(bool wait) {} void setWaitCursor(bool wait) override {}
double getWindowRefreshRate() const { return 60.0; } double getWindowRefreshRate() const override { return 60.0; }
void setWindowFrameDefault() {} void setWindowFrameDefault() override {}
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const {} void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const override {}
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const {} void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const override {}
void setWindowFrame(float x, float y, float w, float h) {} void setWindowFrame(float x, float y, float w, float h) override {}
void setWindowFrame(int x, int y, int w, int h) {} void setWindowFrame(int x, int y, int w, int h) override {}
float getVirtualPixelFactor() const { return 0; } float getVirtualPixelFactor() const override { return 0; }
void setStyle(EWindowStyle /*style*/) {} void setStyle(EWindowStyle /*style*/) override {}
EWindowStyle getStyle() const { return EWindowStyle::None; } EWindowStyle getStyle() const override { return EWindowStyle::None; }
bool isFullscreen() const { return false; } bool isFullscreen() const override { return false; }
void setFullscreen(bool fs) {} void setFullscreen(bool fs) override {}
void claimKeyboardFocus(const int coord[2]) {} void claimKeyboardFocus(const int coord[2]) override {}
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) { return false; } bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) override { return false; }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return std::unique_ptr<uint8_t[]>(); } std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) override { return std::unique_ptr<uint8_t[]>(); }
int waitForRetrace() { return 1; } int waitForRetrace() override { return 1; }
uintptr_t getPlatformHandle() const { return 0; } uintptr_t getPlatformHandle() const override { return 0; }
ETouchType getTouchType() const { return ETouchType::None; } ETouchType getTouchType() const override { return ETouchType::None; }
IGraphicsCommandQueue* getCommandQueue() { return m_gfxCtx.getCommandQueue(); } IGraphicsCommandQueue* getCommandQueue() override { return m_gfxCtx.getCommandQueue(); }
IGraphicsDataFactory* getDataFactory() { return m_gfxCtx.getDataFactory(); } IGraphicsDataFactory* getDataFactory() override { return m_gfxCtx.getDataFactory(); }
IGraphicsDataFactory* getMainContextDataFactory() { return m_gfxCtx.getMainContextDataFactory(); } IGraphicsDataFactory* getMainContextDataFactory() override { return m_gfxCtx.getMainContextDataFactory(); }
IGraphicsDataFactory* getLoadContextDataFactory() { return m_gfxCtx.getLoadContextDataFactory(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_gfxCtx.getLoadContextDataFactory(); }
}; };
std::shared_ptr<IWindow> _WindowWaylandNew(std::string_view title) { return std::make_shared<WindowWayland>(title); } std::shared_ptr<IWindow> _WindowWaylandNew(std::string_view title) { return std::make_shared<WindowWayland>(title); }

View File

@ -1,26 +1,28 @@
#include "boo/IWindow.hpp" #include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp"
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/graphicsdev/GL.hpp" #include "boo/IGraphicsContext.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp" #include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "boo/graphicsdev/GL.hpp"
#include "boo/graphicsdev/glew.h" #include "boo/graphicsdev/glew.h"
#include "../Common.hpp" #include "lib/Common.hpp"
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
#include "boo/graphicsdev/Vulkan.hpp" #include "boo/graphicsdev/Vulkan.hpp"
#include <X11/Xlib-xcb.h> #include <X11/Xlib-xcb.h>
#endif #endif
#include <limits.h> #include <climits>
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring> #include <cstring>
#include <memory>
#include <string>
#include <thread> #include <thread>
#include <mutex> #include <unordered_set>
#include <condition_variable>
#include <unistd.h>
#include <GL/glx.h> #include <GL/glx.h>
@ -32,9 +34,9 @@
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include "logvisor/logvisor.hpp" #include <logvisor/logvisor.hpp>
#include "XlibCommon.hpp" #include "lib/x11/XlibCommon.hpp"
#define REF_DPMM 3.78138 #define REF_DPMM 3.78138
#define FS_ATOM "_NET_WM_STATE_FULLSCREEN" #define FS_ATOM "_NET_WM_STATE_FULLSCREEN"
@ -59,7 +61,7 @@
#undef False #undef False
#undef True #undef True
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); using glXCreateContextAttribsARBProc = GLXContext (*)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
static bool s_glxError; static bool s_glxError;
static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) { static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) {
@ -227,7 +229,7 @@ struct XlibAtoms {
m_imagePng = XInternAtom(disp, "image/png", false); m_imagePng = XInternAtom(disp, "image/png", false);
} }
}; };
static XlibAtoms* S_ATOMS = NULL; static XlibAtoms* S_ATOMS = nullptr;
static Atom GetClipboardTypeAtom(EClipboardType t) { static Atom GetClipboardTypeAtom(EClipboardType t) {
switch (t) { switch (t) {
@ -356,7 +358,7 @@ public:
visualIdOut = m_visualid; visualIdOut = m_visualid;
} }
void destroy() { void destroy() override {
if (m_glxCtx) { if (m_glxCtx) {
glXDestroyContext(m_xDisp, m_glxCtx); glXDestroyContext(m_xDisp, m_glxCtx);
m_glxCtx = nullptr; m_glxCtx = nullptr;
@ -371,23 +373,23 @@ public:
} }
} }
~GraphicsContextXlibGLX() { destroy(); } ~GraphicsContextXlibGLX() override { destroy(); }
void resized(const SWindowRect& rect) {} void resized(const SWindowRect& rect) override {}
void _setCallback(IWindowCallback* cb) { m_callback = cb; } void _setCallback(IWindowCallback* cb) override { m_callback = cb; }
EGraphicsAPI getAPI() const { return m_api; } EGraphicsAPI getAPI() const override { return m_api; }
EPixelFormat getPixelFormat() const { return m_pf; } EPixelFormat getPixelFormat() const override { return m_pf; }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void*) { bool initializeContext(void*) override {
if (!glXCreateContextAttribsARB) { if (!glXCreateContextAttribsARB) {
glXCreateContextAttribsARB = glXCreateContextAttribsARB =
(glXCreateContextAttribsARBProc)glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB"); (glXCreateContextAttribsARBProc)glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB");
@ -424,25 +426,25 @@ public:
return true; return true;
} }
void makeCurrent() { void makeCurrent() override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_glxCtx)) if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_glxCtx))
Log.report(logvisor::Fatal, fmt("unable to make GLX context current")); Log.report(logvisor::Fatal, fmt("unable to make GLX context current"));
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void postInit() { void postInit() override {
GLXExtensionCheck(); GLXExtensionCheck();
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
GLXEnableVSync(m_xDisp, m_glxWindow); GLXEnableVSync(m_xDisp, m_glxWindow);
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
IGraphicsCommandQueue* getCommandQueue() { return m_commandQueue.get(); } IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue.get(); }
IGraphicsDataFactory* getDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getMainContextDataFactory() { IGraphicsDataFactory* getMainContextDataFactory() override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
if (!m_mainCtx) { if (!m_mainCtx) {
s_glxError = false; s_glxError = false;
@ -458,7 +460,7 @@ public:
return getDataFactory(); return getDataFactory();
} }
IGraphicsDataFactory* getLoadContextDataFactory() { IGraphicsDataFactory* getLoadContextDataFactory() override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
if (!m_loadCtx) { if (!m_loadCtx) {
s_glxError = false; s_glxError = false;
@ -474,7 +476,7 @@ public:
return getDataFactory(); return getDataFactory();
} }
void present() { glXSwapBuffers(m_xDisp, m_glxWindow); } void present() override { glXSwapBuffers(m_xDisp, m_glxWindow); }
}; };
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
@ -510,7 +512,7 @@ public:
visualIdOut = screen->root_visual->visualid; visualIdOut = screen->root_visual->visualid;
} }
void destroy() { void destroy() override {
VulkanContext::Window& m_windowCtx = *m_ctx->m_windows[m_parentWindow]; VulkanContext::Window& m_windowCtx = *m_ctx->m_windows[m_parentWindow];
m_windowCtx.m_swapChains[0].destroy(m_ctx->m_dev); m_windowCtx.m_swapChains[0].destroy(m_ctx->m_dev);
m_windowCtx.m_swapChains[1].destroy(m_ctx->m_dev); m_windowCtx.m_swapChains[1].destroy(m_ctx->m_dev);
@ -520,28 +522,28 @@ public:
} }
} }
~GraphicsContextXlibVulkan() { destroy(); } ~GraphicsContextXlibVulkan() override { destroy(); }
VulkanContext::Window* m_windowCtx = nullptr; VulkanContext::Window* m_windowCtx = nullptr;
void resized(const SWindowRect& rect) { void resized(const SWindowRect& rect) override {
if (m_windowCtx) if (m_windowCtx)
m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace, rect); m_ctx->resizeSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace, rect);
} }
void _setCallback(IWindowCallback* cb) { m_callback = cb; } void _setCallback(IWindowCallback* cb) override { m_callback = cb; }
EGraphicsAPI getAPI() const { return m_api; } EGraphicsAPI getAPI() const override { return m_api; }
EPixelFormat getPixelFormat() const { return m_pf; } EPixelFormat getPixelFormat() const override { return m_pf; }
void setPixelFormat(EPixelFormat pf) { void setPixelFormat(EPixelFormat pf) override {
if (pf > EPixelFormat::RGBAF32_Z24) if (pf > EPixelFormat::RGBAF32_Z24)
return; return;
m_pf = pf; m_pf = pf;
} }
bool initializeContext(void* getVkProc) { bool initializeContext(void* getVkProc) override {
if (m_ctx->m_instance == VK_NULL_HANDLE) if (m_ctx->m_instance == VK_NULL_HANDLE)
m_ctx->initVulkan(APP->getUniqueName(), PFN_vkGetInstanceProcAddr(getVkProc)); m_ctx->initVulkan(APP->getUniqueName(), PFN_vkGetInstanceProcAddr(getVkProc));
@ -637,19 +639,19 @@ public:
return true; return true;
} }
void makeCurrent() {} void makeCurrent() override {}
void postInit() {} void postInit() override {}
IGraphicsCommandQueue* getCommandQueue() { return m_commandQueue.get(); } IGraphicsCommandQueue* getCommandQueue() override { return m_commandQueue.get(); }
IGraphicsDataFactory* getDataFactory() { return m_dataFactory.get(); } IGraphicsDataFactory* getDataFactory() override { return m_dataFactory.get(); }
IGraphicsDataFactory* getMainContextDataFactory() { return getDataFactory(); } IGraphicsDataFactory* getMainContextDataFactory() override { return getDataFactory(); }
IGraphicsDataFactory* getLoadContextDataFactory() { return getDataFactory(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return getDataFactory(); }
void present() {} void present() override {}
}; };
#endif #endif
@ -732,6 +734,7 @@ public:
m_gfxCtx.reset(new GraphicsContextXlibGLX(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this, display, m_gfxCtx.reset(new GraphicsContextXlibGLX(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this, display,
defaultScreen, lastCtx, m_visualId, glCtx)); defaultScreen, lastCtx, m_visualId, glCtx));
m_openGL = true; m_openGL = true;
Log.report(logvisor::Warning, fmt("OPENGL HAS BEEN DEPRECATED, IT IS HIGHLY RECOMMENDED TO BUILD AND USE VULKAN INSTEAD"));
} }
XVisualInfo visTemplate; XVisualInfo visTemplate;
@ -848,38 +851,38 @@ public:
} }
} }
~WindowXlib() { ~WindowXlib() override {
_cleanup(); _cleanup();
if (APP) if (APP)
APP->_deletedWindow(this); APP->_deletedWindow(this);
} }
void setCallback(IWindowCallback* cb) { void setCallback(IWindowCallback* cb) override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
m_callback = cb; m_callback = cb;
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void closeWindow() { void closeWindow() override {
// TODO: Free window resources and prevent further access // TODO: Free window resources and prevent further access
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
XUnmapWindow(m_xDisp, m_windowId); XUnmapWindow(m_xDisp, m_windowId);
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void showWindow() { void showWindow() override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
XMapWindow(m_xDisp, m_windowId); XMapWindow(m_xDisp, m_windowId);
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void hideWindow() { void hideWindow() override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
XUnmapWindow(m_xDisp, m_windowId); XUnmapWindow(m_xDisp, m_windowId);
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
std::string getTitle() { std::string getTitle() override {
unsigned long nitems; unsigned long nitems;
Atom actualType; Atom actualType;
int actualFormat; int actualFormat;
@ -897,7 +900,7 @@ public:
return std::string(); return std::string();
} }
void setTitle(std::string_view title) { void setTitle(std::string_view title) override {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
/* Set the title of the window */ /* Set the title of the window */
@ -914,7 +917,7 @@ public:
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void setCursor(EMouseCursor cursor) { void setCursor(EMouseCursor cursor) override {
if (cursor == m_cursor && !m_cursorWait) if (cursor == m_cursor && !m_cursorWait)
return; return;
m_cursor = cursor; m_cursor = cursor;
@ -923,7 +926,7 @@ public:
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void setWaitCursor(bool wait) { void setWaitCursor(bool wait) override {
if (wait && !m_cursorWait) { if (wait && !m_cursorWait) {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
XDefineCursor(m_xDisp, m_windowId, X_CURSORS.m_wait); XDefineCursor(m_xDisp, m_windowId, X_CURSORS.m_wait);
@ -942,7 +945,7 @@ public:
return 60.0; return 60.0;
} }
double getWindowRefreshRate() const { double getWindowRefreshRate() const override {
BOO_MSAN_NO_INTERCEPT BOO_MSAN_NO_INTERCEPT
double ret = 60.0; double ret = 60.0;
int nmonitors; int nmonitors;
@ -969,7 +972,7 @@ public:
return ret; return ret;
} }
void setWindowFrameDefault() { void setWindowFrameDefault() override {
BOO_MSAN_NO_INTERCEPT BOO_MSAN_NO_INTERCEPT
int x, y, w, h, nmonitors; int x, y, w, h, nmonitors;
Screen* screen = DefaultScreenOfDisplay(m_xDisp); Screen* screen = DefaultScreenOfDisplay(m_xDisp);
@ -986,7 +989,7 @@ public:
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const override {
BOO_MSAN_NO_INTERCEPT BOO_MSAN_NO_INTERCEPT
XWindowAttributes attrs = {}; XWindowAttributes attrs = {};
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
@ -998,7 +1001,7 @@ public:
hOut = attrs.height; hOut = attrs.height;
} }
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const { void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const override {
BOO_MSAN_NO_INTERCEPT BOO_MSAN_NO_INTERCEPT
XWindowAttributes attrs = {}; XWindowAttributes attrs = {};
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
@ -1010,7 +1013,7 @@ public:
hOut = attrs.height; hOut = attrs.height;
} }
void setWindowFrame(float x, float y, float w, float h) { void setWindowFrame(float x, float y, float w, float h) override {
BOO_MSAN_NO_INTERCEPT BOO_MSAN_NO_INTERCEPT
XWindowChanges values = {(int)x, (int)y, (int)w, (int)h}; XWindowChanges values = {(int)x, (int)y, (int)w, (int)h};
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
@ -1018,7 +1021,7 @@ public:
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void setWindowFrame(int x, int y, int w, int h) { void setWindowFrame(int x, int y, int w, int h) override {
BOO_MSAN_NO_INTERCEPT BOO_MSAN_NO_INTERCEPT
XWindowChanges values = {x, y, w, h}; XWindowChanges values = {x, y, w, h};
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
@ -1026,9 +1029,9 @@ public:
XUnlockDisplay(m_xDisp); XUnlockDisplay(m_xDisp);
} }
float getVirtualPixelFactor() const { return m_pixelFactor; } float getVirtualPixelFactor() const override { return m_pixelFactor; }
bool isFullscreen() const { bool isFullscreen() const override {
return m_inFs; return m_inFs;
unsigned long nitems; unsigned long nitems;
Atom actualType; Atom actualType;
@ -1054,7 +1057,7 @@ public:
return false; return false;
} }
void setStyle(EWindowStyle style) { void setStyle(EWindowStyle style) override {
struct { struct {
unsigned long flags; unsigned long flags;
unsigned long functions; unsigned long functions;
@ -1086,9 +1089,9 @@ public:
m_styleFlags = style; m_styleFlags = style;
} }
EWindowStyle getStyle() const { return m_styleFlags; } EWindowStyle getStyle() const override { return m_styleFlags; }
void setFullscreen(bool fs) { void setFullscreen(bool fs) override {
if (fs == m_inFs) if (fs == m_inFs)
return; return;
@ -1121,7 +1124,7 @@ public:
} }
} m_clipData; } m_clipData;
void claimKeyboardFocus(const int coord[2]) { void claimKeyboardFocus(const int coord[2]) override {
if (m_xIC) { if (m_xIC) {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
if (!coord) { if (!coord) {
@ -1139,7 +1142,7 @@ public:
} }
} }
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) { bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) override {
Atom xType = GetClipboardTypeAtom(type); Atom xType = GetClipboardTypeAtom(type);
if (!xType) if (!xType)
return false; return false;
@ -1155,7 +1158,7 @@ public:
return true; return true;
} }
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) override {
Atom xType = GetClipboardTypeAtom(type); Atom xType = GetClipboardTypeAtom(type);
if (!xType) if (!xType)
return {}; return {};
@ -1273,7 +1276,7 @@ public:
return lhs.tv_nsec - rhs.tv_nsec; return lhs.tv_nsec - rhs.tv_nsec;
} }
int waitForRetrace() { int waitForRetrace() override {
BOO_MSAN_NO_INTERCEPT BOO_MSAN_NO_INTERCEPT
struct timespec tp = {}; struct timespec tp = {};
clock_gettime(CLOCK_REALTIME, &tp); clock_gettime(CLOCK_REALTIME, &tp);
@ -1306,7 +1309,7 @@ public:
} }
} }
uintptr_t getPlatformHandle() const { return (uintptr_t)m_windowId; } uintptr_t getPlatformHandle() const override { return (uintptr_t)m_windowId; }
void _pointingDeviceChanged(int deviceId) { void _pointingDeviceChanged(int deviceId) {
int nDevices; int nDevices;
@ -1414,7 +1417,7 @@ public:
} }
#endif #endif
bool _incomingEvent(void* e) { bool _incomingEvent(void* e) override {
XEvent* event = (XEvent*)e; XEvent* event = (XEvent*)e;
switch (event->type) { switch (event->type) {
case SelectionRequest: { case SelectionRequest: {
@ -1708,7 +1711,7 @@ public:
return false; return false;
} }
void _cleanup() { void _cleanup() override {
if (m_gfxCtx) { if (m_gfxCtx) {
XLockDisplay(m_xDisp); XLockDisplay(m_xDisp);
m_gfxCtx->destroy(); m_gfxCtx->destroy();
@ -1720,15 +1723,15 @@ public:
} }
} }
ETouchType getTouchType() const { return m_touchType; } ETouchType getTouchType() const override { return m_touchType; }
IGraphicsCommandQueue* getCommandQueue() { return m_gfxCtx->getCommandQueue(); } IGraphicsCommandQueue* getCommandQueue() override { return m_gfxCtx->getCommandQueue(); }
IGraphicsDataFactory* getDataFactory() { return m_gfxCtx->getDataFactory(); } IGraphicsDataFactory* getDataFactory() override { return m_gfxCtx->getDataFactory(); }
IGraphicsDataFactory* getMainContextDataFactory() { return m_gfxCtx->getMainContextDataFactory(); } IGraphicsDataFactory* getMainContextDataFactory() override { return m_gfxCtx->getMainContextDataFactory(); }
IGraphicsDataFactory* getLoadContextDataFactory() { return m_gfxCtx->getLoadContextDataFactory(); } IGraphicsDataFactory* getLoadContextDataFactory() override { return m_gfxCtx->getLoadContextDataFactory(); }
bool _isWindowMapped() { bool _isWindowMapped() {
XWindowAttributes attr; XWindowAttributes attr;

@ -1 +1 @@
Subproject commit dcd0ffcaece7f9ea3785d0ffca30a82cd60c573c Subproject commit f623ace3b4620c56722a1460ff2d9db61621f659

Some files were not shown because too many files have changed in this diff Show More