build: unpack XAudio2_7.dll at init

Use a Windows resource for the XAudio2_7.dll which may not be installed
by the user.

Unpack it at initialization of the XAudio2 driver into a temp directory
and load it.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
This commit is contained in:
Rafael Kitover 2024-10-06 21:31:56 +00:00
parent 709a322337
commit 6ed20a51cc
No known key found for this signature in database
GPG Key ID: 08AB596679D86240
6 changed files with 72 additions and 2 deletions

View File

@ -659,6 +659,20 @@ list(APPEND VBAM_LOCALIZABLE_FILES
${CMAKE_SOURCE_DIR}/src/core/gba/gbaLink.cpp ${CMAKE_SOURCE_DIR}/src/core/gba/gbaLink.cpp
) )
if(WIN32 AND (X86_64 OR X86_32) AND ENABLE_XAUDIO2)
if(NOT DEFINED XAUDIO_27_BIN_DIR)
set(XAUDIO_27_BIN_DIR ${CMAKE_SOURCE_DIR}/win32-deps/xaudio27-dll)
endif()
if(X86_64)
set(XAUDIO_27_DLL ${XAUDIO_27_BIN_DIR}/x64/XAudio2_7.dll)
elseif(X86_32)
set(XAUDIO_27_DLL ${XAUDIO_27_BIN_DIR}/x86/XAudio2_7.dll)
endif()
configure_file(audio/internal/xaudio27-dll-path.h.in ${CMAKE_BINARY_DIR}/xaudio27-dll-path.h)
endif()
if(APPLE) if(APPLE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks") set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks")

View File

@ -2,9 +2,11 @@
#error "This file should only be compiled if XAudio2 is enabled" #error "This file should only be compiled if XAudio2 is enabled"
#endif #endif
#include "wx/audio/internal/xaudio27-dll-rc.h"
#include "wx/audio/internal/xaudio2.h" #include "wx/audio/internal/xaudio2.h"
#include <cstdio> #include <cstdio>
#include <cstdlib>
#include <string> #include <string>
#include <vector> #include <vector>
@ -19,8 +21,17 @@
#endif #endif
#include <wx/arrstr.h> #include <wx/arrstr.h>
#include <wx/chartype.h>
#include <wx/dir.h>
#include <wx/dynlib.h>
#include <wx/file.h>
#include <wx/filename.h>
#include <wx/log.h> #include <wx/log.h>
#include <wx/process.h>
#include <wx/msw/private.h>
#include <wx/string.h>
#include <wx/translation.h> #include <wx/translation.h>
#include <wx/utils.h>
#include "core/base/sound_driver.h" #include "core/base/sound_driver.h"
#include "core/base/system.h" // for systemMessage() #include "core/base/system.h" // for systemMessage()
@ -199,6 +210,7 @@ public:
void device_change(); void device_change();
inline static wxString temp_dir_path;
private: private:
void close(); void close();
@ -221,6 +233,10 @@ private:
volatile bool device_changed; volatile bool device_changed;
wxDynamicLibrary xaudio2_dll;
typedef HRESULT (*func_XAudio2Create)(IXAudio2**, UINT32);
func_XAudio2Create dll_XAudio2Create = nullptr;
IXAudio2* xaud; IXAudio2* xaud;
IXAudio2MasteringVoice* mVoice; // listener IXAudio2MasteringVoice* mVoice; // listener
IXAudio2SourceVoice* sVoice; // sound source IXAudio2SourceVoice* sVoice; // sound source
@ -245,11 +261,41 @@ XAudio2_Output::XAudio2_Output() {
ZeroMemory(&buf, sizeof(buf)); ZeroMemory(&buf, sizeof(buf));
ZeroMemory(&vState, sizeof(vState)); ZeroMemory(&vState, sizeof(vState));
g_notifier.do_register(this); g_notifier.do_register(this);
HRSRC res = FindResource(wxGetInstance(), MAKEINTRESOURCE(XAUDIO27_DLL_RC), RT_RCDATA);
if (!res)
wxLogFatalError("Could not find resource for 'XAudio2_7.dll'.");
HGLOBAL res_handle = LoadResource(NULL, res);
if (!res_handle)
wxLogFatalError("Could not find resource for 'XAudio2_7.dll'.");
uint64_t res_size = SizeofResource(NULL, res);
char *res_data = (char *)LockResource(res_handle);
wxString pid = wxString{} << wxProcessEvent{}.GetPid();
temp_dir_path = wxFileName::GetTempDir() + "/visualboyadvance-m/" + pid;
wxDir{}.Make(temp_dir_path, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
wxString dll_path = temp_dir_path + "/XAudio2_7.dll";
wxFile dll(dll_path, wxFile::write);
dll.Write((void *)res_data, res_size);
dll.Close();
xaudio2_dll.Load(dll_path, wxDL_VERBATIM | wxDL_QUIET);
dll_XAudio2Create = reinterpret_cast<func_XAudio2Create>(xaudio2_dll.GetSymbol("XAudio2Create"));
} }
XAudio2_Output::~XAudio2_Output() { XAudio2_Output::~XAudio2_Output() {
g_notifier.do_unregister(this); g_notifier.do_unregister(this);
close(); close();
HMODULE hmod = xaudio2_dll.Detach();
while(::FreeLibrary(hmod)) {
wxMilliSleep(50);
}
} }
void XAudio2_Output::close() { void XAudio2_Output::close() {
@ -291,7 +337,7 @@ bool XAudio2_Output::init(long sampleRate) {
HRESULT hr; HRESULT hr;
// Initialize XAudio2 // Initialize XAudio2
hr = XAudio2Create(&xaud, 0); hr = dll_XAudio2Create(&xaud, 0);
if (hr != S_OK) { if (hr != S_OK) {
wxLogError(_("The XAudio2 interface failed to initialize!")); wxLogError(_("The XAudio2 interface failed to initialize!"));

View File

@ -0,0 +1 @@
#define XAUDIO27_DLL_PATH "@XAUDIO_27_DLL@"

View File

@ -0,0 +1,6 @@
#ifndef XAUDIO27_RC_H
#define XAUDIO27_RC_H
#define XAUDIO27_DLL_RC 301
#endif /* XAUDIO27_RC_H */

View File

@ -19,8 +19,11 @@ AAAAA_MAINICON ICON "icons/visualboyadvance-m.ico"
#include "autoupdater/wxmsw/winsparkle-rc.h" #include "autoupdater/wxmsw/winsparkle-rc.h"
#include "winsparkle-path.h" #include "winsparkle-path.h"
#include "audio/internal/xaudio27-dll-rc.h"
#include "xaudio27-dll-path.h"
WINSPARKLE_DLL_RC RCDATA WINSPARKLE_DLL_PATH WINSPARKLE_DLL_RC RCDATA WINSPARKLE_DLL_PATH
XAUDIO27_DLL_RC RCDATA XAUDIO27_DLL_PATH
#endif /* NO_ONLINEUPDATES */ #endif /* NO_ONLINEUPDATES */

@ -1 +1 @@
Subproject commit 0a1cdd9c04f7727e2d477b070e846c5b971761de Subproject commit b9cfd0b1ea6108c65c175e380a8c35e620ac1f24