Compare commits

...

12 Commits

Author SHA1 Message Date
Casper Jeukendrup 04bb125b93 Remove some things 2023-05-06 17:57:52 +02:00
Casper Jeukendrup 60c090244f Just copy those files please 2023-05-06 15:49:05 +02:00
Casper Jeukendrup 1173233f95
MKDIR 2023-05-06 00:28:24 +02:00
Casper Jeukendrup b03f759279
Two in one 2023-05-05 23:30:33 +02:00
Casper Jeukendrup 1d21d81be8
Copy more info to the artifact 2023-05-05 23:22:58 +02:00
Casper Jeukendrup f0d99f763e
try if re-running CMake is the problem 2023-05-05 23:19:15 +02:00
Casper Jeukendrup bfad6640e3
Disable signing for msi 2023-05-05 23:18:15 +02:00
Casper Jeukendrup 68674bd1ba
Verbose build log 2023-05-05 23:18:15 +02:00
Casper Jeukendrup 553cd881ef
Add some test about throwing and catching exceptions 2023-05-05 23:18:15 +02:00
Casper Jeukendrup ca6fb026ca
Add an extreme amount of logging statements to wasapiaudioclient 2023-05-05 23:18:15 +02:00
Casper Jeukendrup 74d79500d5
Please don't be annoying 2023-05-05 23:18:14 +02:00
Casper Jeukendrup f10f241ded
Build in release mode 2023-05-05 23:18:14 +02:00
6 changed files with 250 additions and 116 deletions

View File

@ -30,10 +30,10 @@ jobs:
build_mu4_x64:
runs-on: windows-2022
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
# - name: Cancel Previous Runs
# uses: styfle/cancel-workflow-action@0.11.0
# with:
# access_token: ${{ github.token }}
- name: Clone repository (default)
uses: actions/checkout@v3
if: ${{ github.event_name != 'schedule' || github.event.schedule == '0 3 */1 */1 *' }}
@ -109,7 +109,7 @@ jobs:
DO_PUBLISH='false'
fi
ADD_INFO="_${GITHUB_REF#refs/heads/}"
ADD_INFO="_${GITHUB_REF#refs/heads/}_Release"
if [ "${{ github.event_name }}" == "schedule" ] && [ "${{ github.event.schedule }}" == "0 5 */1 */1 *" ]; then ADD_INFO="_${CURRENT_RELEASE_BRANCH}"; fi
if [ "${{ github.event_name }}" == "pull_request" ]; then ADD_INFO="_${{ github.event.pull_request.number }}_${pull_request_title}"; fi
UPLOAD_ARTIFACT_NAME="$(tr '":<>|*?/\\' '_' <<<"MU4_${BUILD_NUMBER}_Win${ADD_INFO}")"
@ -186,25 +186,25 @@ jobs:
IF ${{ secrets.WIN_SIGN_CERTIFICATE_PASSWORD != 0 }} == true ( SET S_P=${{ secrets.WIN_SIGN_CERTIFICATE_PASSWORD }} ) ELSE ( SET S_P="''" )
IF ${{ env.BUILD_MODE }} == stable_build ( SET GUID=${{ secrets.WIN_MSI_STABLE_MU4_GUID }} ) ELSE ( SET GUID=${{ secrets.WIN_MSI_TESTING_MU4_GUID }} )
build\ci\windows\package.bat --signsecret %S_S% --signpass %S_P% --guid %GUID%
- name: Checksum
if: env.DO_BUILD == 'true'
run: |
bash ./build/ci/tools/checksum.sh
# - name: Checksum
# if: env.DO_BUILD == 'true'
# run: |
# bash ./build/ci/tools/checksum.sh
- name: Upload dump symbols
if: env.DO_UPLOAD_SYMBOLS == 'true'
shell: bash
run: |
bash ./build/ci/tools/sentry_syms_upload.sh -t ${{ secrets.SENTRY_AUTH_TOKEN }} -p ${SENTRY_PROJECT}
- name: Publish package
if: env.DO_PUBLISH == 'true'
shell: bash
run: |
bash ./build/ci/tools/osuosl/publish.sh -s ${{ secrets.OSUOSL_SSH_ENCRYPT_SECRET }} --os windows -v 4
- name: AppCast
if: env.DO_BUILD == 'true'
shell: bash
run: |
bash ./build/ci/tools/sparkle_appcast_gen.sh -p windows
# - name: Publish package
# if: env.DO_PUBLISH == 'true'
# shell: bash
# run: |
# bash ./build/ci/tools/osuosl/publish.sh -s ${{ secrets.OSUOSL_SSH_ENCRYPT_SECRET }} --os windows -v 4
# - name: AppCast
# if: env.DO_BUILD == 'true'
# shell: bash
# run: |
# bash ./build/ci/tools/sparkle_appcast_gen.sh -p windows
- name: Upload artifacts on GitHub
if: ${{ always() }}
uses: actions/upload-artifact@v3
@ -216,10 +216,10 @@ jobs:
build_portable:
runs-on: windows-2022
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
# - name: Cancel Previous Runs
# uses: styfle/cancel-workflow-action@0.11.0
# with:
# access_token: ${{ github.token }}
- name: Clone repository
uses: actions/checkout@v3
with:
@ -281,15 +281,15 @@ jobs:
shell: cmd
run: |
build\ci\windows\package.bat --portable ON
- name: Checksum
if: env.DO_BUILD == 'true'
run: |
bash ./build/ci/tools/checksum.sh
- name: Publish package
if: env.DO_PUBLISH == 'true'
run: |
build\ci\windows\publish.bat --secret ${{ secrets.OSUOSL_SSH_ENCRYPT_SECRET }}
shell: cmd
# - name: Checksum
# if: env.DO_BUILD == 'true'
# run: |
# bash ./build/ci/tools/checksum.sh
# - name: Publish package
# if: env.DO_PUBLISH == 'true'
# run: |
# build\ci\windows\publish.bat --secret ${{ secrets.OSUOSL_SSH_ENCRYPT_SECRET }}
# shell: cmd
- name: Upload artifacts on GitHub
if: env.DO_BUILD == 'true'
uses: actions/upload-artifact@v3

View File

@ -32,8 +32,6 @@ if (MUSESCORE_UNSTABLE)
endif (git_date)
endif (MUSESCORE_UNSTABLE)
SET(CPACK_NSIS_COMPRESSOR "/FINAL /SOLID lzma")
IF(MINGW OR MSVC)
SET(CPACK_PACKAGE_INSTALL_DIRECTORY ${MUSESCORE_NAME_VERSION})
SET(CPACK_PACKAGE_NAME ${MUSESCORE_NAME})
@ -42,30 +40,10 @@ IF(MINGW OR MSVC)
# There is a bug in NSI that does not handle full unix paths properly. Make
# sure there is at least one set of four (4) backslashes.
SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/build/packaging\\\\installer_head_nsis.bmp")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\${MSCORE_EXECUTABLE_NAME}.exe,0")
SET(CPACK_NSIS_DISPLAY_NAME "${MUSESCORE_NAME} ${MUSESCORE_VERSION_FULL}")
SET(CPACK_NSIS_HELP_LINK "https://www.musescore.org/")
SET(CPACK_NSIS_URL_INFO_ABOUT "https://www.musescore.org/")
SET(CPACK_NSIS_CONTACT "info@musescore.org")
SET(CPACK_NSIS_MODIFY_PATH OFF)
SET(CPACK_STRIP_FILES "${MSCORE_EXECUTABLE_NAME}.exe")
# File types association:
message(STATUS "[Packaging.cmake] PACKAGE_FILE_ASSOCIATION: ${MUE_ENABLE_FILE_ASSOCIATION}")
IF (MUE_ENABLE_FILE_ASSOCIATION)
SET(CPACK_NSIS_DEFINES "!include ${PROJECT_SOURCE_DIR}/build/packaging\\\\FileAssociation.nsh")
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
\\\${registerExtension} \\\"MuseScore File\\\" \\\".mscz\\\" \\\"\\\$INSTDIR\\\\bin\\\\${MSCORE_EXECUTABLE_NAME}.exe\\\"
\\\${registerExtension} \\\"MuseScore Uncompressed File\\\" \\\".mscx\\\" \\\"\\\$INSTDIR\\\\bin\\\\${MSCORE_EXECUTABLE_NAME}.exe\\\"
\\\${registerExtension} \\\"MuseScore Uncompressde File\\\" \\\".mscs\\\" \\\"\\\$INSTDIR\\\\bin\\\\${MSCORE_EXECUTABLE_NAME}.exe\\\"
")
SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
\\\${unregisterExtension} \\\".mscz\\\" \\\"MuseScore File\\\"
\\\${unregisterExtension} \\\".mscx\\\" \\\"MuseScore Uncompressed File\\\"
\\\${unregisterExtension} \\\".mscs\\\" \\\"MuseScore Uncompressed File\\\"
")
list(APPEND CPACK_WIX_CANDLE_EXTRA_FLAGS -dCPACK_WIX_FILE_ASSOCIATION=ON)
ELSE(MUE_ENABLE_FILE_ASSOCIATION)
list(APPEND CPACK_WIX_CANDLE_EXTRA_FLAGS -dCPACK_WIX_FILE_ASSOCIATION=OFF)

View File

@ -27,14 +27,14 @@ IF NOT %TARGET_PROCESSOR_BITS% == 64 (
)
SET /p BUILD_MODE=<%ARTIFACTS_DIR%\env\build_mode.env
SET "MUSESCORE_BUILD_MODE=dev"
IF %BUILD_MODE% == devel_build ( SET "MUSESCORE_BUILD_MODE=dev" ) ELSE (
IF %BUILD_MODE% == nightly_build ( SET "MUSESCORE_BUILD_MODE=dev" ) ELSE (
IF %BUILD_MODE% == testing_build ( SET "MUSESCORE_BUILD_MODE=testing" ) ELSE (
IF %BUILD_MODE% == stable_build ( SET "MUSESCORE_BUILD_MODE=release" ) ELSE (
ECHO "error: unknown BUILD_MODE: %BUILD_MODE%"
EXIT /b 1
))))
SET "MUSESCORE_BUILD_MODE=release"
@REM IF %BUILD_MODE% == devel_build ( SET "MUSESCORE_BUILD_MODE=dev" ) ELSE (
@REM IF %BUILD_MODE% == nightly_build ( SET "MUSESCORE_BUILD_MODE=dev" ) ELSE (
@REM IF %BUILD_MODE% == testing_build ( SET "MUSESCORE_BUILD_MODE=testing" ) ELSE (
@REM IF %BUILD_MODE% == stable_build ( SET "MUSESCORE_BUILD_MODE=release" ) ELSE (
@REM ECHO "error: unknown BUILD_MODE: %BUILD_MODE%"
@REM EXIT /b 1
@REM ))))
ECHO "MUSESCORE_BUILD_MODE: %MUSESCORE_BUILD_MODE%"
ECHO "BUILD_NUMBER: %BUILD_NUMBER%"

View File

@ -52,17 +52,17 @@ IF %BUILD_MODE% == stable_build ( SET PACKAGE_TYPE="msi") ELSE (
)))))
SET DO_SIGN=OFF
IF %PACKAGE_TYPE% == "msi" (
SET DO_SIGN=ON
IF %SIGN_CERTIFICATE_ENCRYPT_SECRET% == "" (
SET DO_SIGN=OFF
ECHO "warning: not set SIGN_CERTIFICATE_ENCRYPT_SECRET"
)
IF %SIGN_CERTIFICATE_PASSWORD% == "" (
SET DO_SIGN=OFF
ECHO "warning: not set SIGN_CERTIFICATE_PASSWORD"
)
)
@REM IF %PACKAGE_TYPE% == "msi" (
@REM SET DO_SIGN=ON
@REM IF %SIGN_CERTIFICATE_ENCRYPT_SECRET% == "" (
@REM SET DO_SIGN=OFF
@REM ECHO "warning: not set SIGN_CERTIFICATE_ENCRYPT_SECRET"
@REM )
@REM IF %SIGN_CERTIFICATE_PASSWORD% == "" (
@REM SET DO_SIGN=OFF
@REM ECHO "warning: not set SIGN_CERTIFICATE_PASSWORD"
@REM )
@REM )
SET /p BUILD_VERSION=<%ARTIFACTS_DIR%\env\build_version.env
SET /p BUILD_NUMBER=<%ARTIFACTS_DIR%\env\build_number.env
@ -147,24 +147,20 @@ IF %BUILD_MODE% == stable_build (
SET PACKAGE_FILE_ASSOCIATION=ON
)
cd "%BUILD_DIR%"
cmake -DMUE_ENABLE_FILE_ASSOCIATION=%PACKAGE_FILE_ASSOCIATION% ..
@REM cmake -DMUE_ENABLE_FILE_ASSOCIATION=%PACKAGE_FILE_ASSOCIATION% ..
SET PATH=%WIX_DIR%;%PATH%
cmake --build . --target package || GOTO END_ERROR
cd ..
ECHO "Create logs dir"
MKDIR %ARTIFACTS_DIR%\logs
MKDIR %ARTIFACTS_DIR%\logs\WIX
MKDIR %ARTIFACTS_DIR%\CPack_Packages
SET WIX_LOG_DIR=win64
IF %TARGET_PROCESSOR_BITS% == 32 ( SET WIX_LOG_DIR=win32 )
SET WIX_LOGS_PATH="%BUILD_DIR%\_CPack_Packages"
ECHO "Copy from %WIX_LOGS_PATH% to %ARTIFACTS_DIR%\CPack_Packages"
SET WIX_LOGS_PATH="%BUILD_DIR%\_CPack_Packages\%WIX_LOG_DIR%\WIX"
ECHO "Copy from %WIX_LOGS_PATH% to %ARTIFACTS_DIR%\logs\WIX"
ECHO .msi > excludedmsi.txt
XCOPY /Y /EXCLUDE:excludedmsi.txt %WIX_LOGS_PATH% %ARTIFACTS_DIR%\logs\WIX
::ECHO .msi > excludedmsi.txt
XCOPY /Y/E/H/C/I %WIX_LOGS_PATH% %ARTIFACTS_DIR%\CPack_Packages
:: find the MSI file without the hardcoded version
for /r %%i in (%BUILD_DIR%\*.msi) do (
@ -188,6 +184,8 @@ IF %DO_SIGN% == ON (
bash ./build/ci/tools/make_artifact_name_env.sh %ARTIFACT_NAME%
GOTO PACK_7z
GOTO END_SUCCESS
:: ============================

View File

@ -87,7 +87,9 @@ function do_build() {
-DCMAKE_SKIP_RPATH="${MUSESCORE_NO_RPATH}" \
ninja -j $JOBS
cat CMakeCache.txt
echo "================================================================================================"
ninja -v -j $JOBS
}

View File

@ -22,22 +22,39 @@
#include "wasapiaudioclient.h"
#include "defer.h"
#include "log.h"
using namespace mu;
using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Media::Devices;
using namespace winrt::Windows::Devices::Enumeration;
#define EEEE_IMPL(c) \
auto funcname________ = FUNCNAME(FUNC_INFO); \
LOGI() << "enter " << c << " " << funcname________; \
DEFER { \
LOGI() << "survived " << c << " " << funcname________; \
};
#define EEEE_EMPTY
#define EEEEE EEEE_IMPL("")
#define EEEE_TRY EEEE_IMPL("try")
#define EEEE_CATCH EEEE_IMPL("catch")
WasapiAudioClient::WasapiAudioClient(HANDLE clientStartedEvent, HANDLE clientFailedToStartEvent, HANDLE clientStoppedEvent)
: m_clientStartedEvent(clientStartedEvent), m_clientFailedToStartEvent(clientFailedToStartEvent), m_clientStoppedEvent(
clientStoppedEvent)
{
EEEEE;
check_hresult(MFStartup(MF_VERSION, MFSTARTUP_LITE));
}
WasapiAudioClient::~WasapiAudioClient()
{
EEEEE;
MFShutdown();
}
@ -100,6 +117,8 @@ unsigned int WasapiAudioClient::channelCount() const
DeviceInformationCollection WasapiAudioClient::availableDevices() const
{
EEEEE;
// Get the string identifier of the audio renderer
hstring AudioSelector = MediaDevice::GetAudioRenderSelector();
@ -109,9 +128,13 @@ DeviceInformationCollection WasapiAudioClient::availableDevices() const
DeviceInformationCollection deviceInfoCollection = nullptr;
try {
EEEE_TRY;
deviceInfoCollection = deviceRequest.get();
} catch (...) {
LOGE() << to_string(hresult_error(to_hresult()).message());
EEEE_CATCH;
auto e = to_hresult();
LOGI() << "survived to_hresult";
LOGE() << to_string(hresult_error(e).message());
}
return deviceInfoCollection;
@ -119,12 +142,15 @@ DeviceInformationCollection WasapiAudioClient::availableDevices() const
hstring WasapiAudioClient::defaultDeviceId() const
{
EEEEE;
return MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
}
void WasapiAudioClient::asyncInitializeAudioDevice(const hstring& deviceId, bool useClosestSupportedFormat) noexcept
{
LOGI() << "enter";
try {
EEEE_TRY;
// This call can be made safely from a background thread because we are asking for the IAudioClient3
// interface of an audio device. Async operation will call back to
// IActivateAudioInterfaceCompletionHandler::ActivateCompleted, which must be an agile interface implementation
@ -134,10 +160,21 @@ void WasapiAudioClient::asyncInitializeAudioDevice(const hstring& deviceId, bool
m_deviceState = DeviceState::Uninitialized;
com_ptr<IActivateAudioInterfaceAsyncOperation> asyncOp;
check_hresult(ActivateAudioInterfaceAsync(m_deviceIdString.c_str(), __uuidof(IAudioClient3), nullptr, this, asyncOp.put()));
LOGI() << "before ActivateAudioInterfaceAsync";
auto hres = ActivateAudioInterfaceAsync(m_deviceIdString.c_str(), __uuidof(IAudioClient3), nullptr, this, asyncOp.put());
LOGI() << "after ActivateAudioInterfaceAsync, before check_hresult";
check_hresult(hres);
LOGI() << "after check_hresult";
} catch (...) {
setStateAndNotify(DeviceState::Error, to_hresult());
EEEE_CATCH;
auto e = to_hresult();
LOGI() << "survived to_hresult";
setStateAndNotify(DeviceState::Error, e);
}
LOGI() << "survived";
}
static void logWAVEFORMATEX(WAVEFORMATEX* format)
@ -159,39 +196,60 @@ static void logWAVEFORMATEX(WAVEFORMATEX* format)
//
HRESULT WasapiAudioClient::ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation) noexcept
{
EEEEE;
try {
EEEE_TRY;
if (m_deviceState != DeviceState::Uninitialized) {
LOGI() << "not uninitialized";
throw hresult_error(E_NOT_VALID_STATE);
}
LOGI() << "survived uninitialized";
// Check for a successful activation result
HRESULT hrActivateResult = S_OK;
com_ptr<::IUnknown> punkAudioInterface;
check_hresult(operation->GetActivateResult(&hrActivateResult, punkAudioInterface.put()));
LOGI() << "before operation->GetActivateResult(&hrActivateResult, punkAudioInterface.put())";
auto hr = operation->GetActivateResult(&hrActivateResult, punkAudioInterface.put());
LOGI() << "going to check hresult of operation->GetActivateResult(&hrActivateResult, punkAudioInterface.put())";
check_hresult(hr);
LOGI() << "survived hresult of operation->GetActivateResult(&hrActivateResult, punkAudioInterface.put())";
check_hresult(hrActivateResult);
LOGI() << "survived check_hresult(hrActivateResult)";
// Remember that we have been activated, but don't raise the event yet.
setState(DeviceState::Activated);
LOGI() << "survived setState(DeviceState::Activated);";
// Get the pointer for the Audio Client
m_audioClient = punkAudioInterface.as<IAudioClient3>();
LOGI() << "survived m_audioClient = punkAudioInterface.as<IAudioClient3>();";
// Configure user defined properties
check_hresult(configureDeviceInternal());
LOGI() << "survived check_hresult(configureDeviceInternal());";
// Initialize the AudioClient in Shared Mode with the user specified buffer
if (!m_isLowLatency) {
check_hresult(m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
m_hnsBufferDuration,
0,
m_mixFormat.get(),
nullptr));
auto h = m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
m_hnsBufferDuration,
0,
m_mixFormat.get(),
nullptr);
LOGI() << "survived m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED,";
check_hresult(h);
LOGI() << "survived check_hresult(m_audioClient->initialize";
} else {
check_hresult(m_audioClient->InitializeSharedAudioStream(AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
m_minPeriodInFrames,
m_mixFormat.get(),
nullptr));
LOGI() << "survived m_audioClient->InitializeSharedAudioStream(AUDCLNT_STREAMFLAGS_EVENTCALLBACK,";
auto h = m_audioClient->InitializeSharedAudioStream(AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
m_minPeriodInFrames,
m_mixFormat.get(),
nullptr);
check_hresult(h);
LOGI() << "survived check_hresult(m_audioClient->InitializeSharedAudioStream";
}
LOGI() << "Initialized WASAPI audio endpoint with: ";
@ -204,25 +262,41 @@ HRESULT WasapiAudioClient::ActivateCompleted(IActivateAudioInterfaceAsyncOperati
LOGI() << "Min period in frames: " << m_minPeriodInFrames;
// Get the maximum size of the AudioClient Buffer
check_hresult(m_audioClient->GetBufferSize(&m_bufferFrames));
hr = m_audioClient->GetBufferSize(&m_bufferFrames);
LOGI() << "survived m_audioClient->GetBufferSize(&m_bufferFrames);";
check_hresult(hr);
LOGI() << "survived check_hresult(m_audioClient->GetBufferSize(&m_bufferFrames);";
// Get the render client
m_audioRenderClient.capture(m_audioClient, &IAudioClient::GetService);
LOGI() << "survived m_audioRenderClient.capture(m_audioClient, &IAudioClient::GetService);";
// Create Async callback for sample events
check_hresult(MFCreateAsyncResult(nullptr, &m_sampleReadyCallback, nullptr, m_sampleReadyAsyncResult.put()));
hr = MFCreateAsyncResult(nullptr, &m_sampleReadyCallback, nullptr, m_sampleReadyAsyncResult.put());
LOGI() << "survived MFCreateAsyncResult(nullptr, &m_sampleReadyCallback, nullptr, m_sampleReadyAsyncResult.put());";
check_hresult(hr);
LOGI() << "survived check_hresult(MFCreateAsyncResult(nullptr, &m_sampleReadyCallback, nullptr, m_sampleReadyAsyncResult.put());";
// Sets the event handle that the system signals when an audio buffer is ready to be processed by the client
check_hresult(m_audioClient->SetEventHandle(m_sampleReadyEvent.get()));
m_audioClient->SetEventHandle(m_sampleReadyEvent.get());
LOGI() << "survived m_audioClient->SetEventHandle(m_sampleReadyEvent.get())";
check_hresult(hr);
LOGI() << "survivied check_hresult(m_audioClient->SetEventHandle(m_sampleReadyEvent.get())";
// Everything succeeded
setStateAndNotify(DeviceState::Initialized, S_OK);
LOGI() << "survivied setStateAndNotify(DeviceState::Initialized, S_OK);";
startPlayback();
LOGI() << "survived startPlayback";
return S_OK;
} catch (...) {
setStateAndNotify(DeviceState::Error, to_hresult());
EEEE_CATCH;
auto e = to_hresult();
LOGI() << "survvied to_hresult";
setStateAndNotify(DeviceState::Error, e);
LOGI() << "survived setStateAndNotify(Error";
m_audioClient = nullptr;
m_audioRenderClient = nullptr;
@ -242,6 +316,7 @@ HRESULT WasapiAudioClient::ActivateCompleted(IActivateAudioInterfaceAsyncOperati
//
UINT32 WasapiAudioClient::getBufferFramesPerPeriod() noexcept
{
EEEEE;
REFERENCE_TIME defaultDevicePeriod = 0;
REFERENCE_TIME minimumDevicePeriod = 0;
@ -255,7 +330,9 @@ UINT32 WasapiAudioClient::getBufferFramesPerPeriod() noexcept
// Get the audio device period
HRESULT hr = m_audioClient->GetDevicePeriod(&defaultDevicePeriod, &minimumDevicePeriod);
LOGI() << "survived m_audioClient->GetDevicePeriod";
if (FAILED(hr)) {
LOGI() << "it failed though";
return 0;
}
@ -270,7 +347,32 @@ UINT32 WasapiAudioClient::getBufferFramesPerPeriod() noexcept
//
HRESULT WasapiAudioClient::configureDeviceInternal() noexcept
{
LOGI() << "Entering configureDeviceInternal; doing some tests first";
try
{
LOGI() << "Throw runtime error";
throw std::runtime_error("");
}
catch (...)
{
LOGI() << "Caught runtime error";
}
try
{
LOGI() << "Throw hresult error";
check_hresult(AUDCLNT_E_UNSUPPORTED_FORMAT);
}
catch (...)
{
LOGI() << "Caught hresult";
HRESULT h = to_hresult();
LOGI() << "Converted hresult: " << h;
}
EEEEE;
try {
EEEE_TRY;
if (m_deviceState != DeviceState::Activated) {
return E_NOT_VALID_STATE;
}
@ -286,7 +388,10 @@ HRESULT WasapiAudioClient::configureDeviceInternal() noexcept
}
LOGI() << "WASAPI: Settings device client properties";
check_hresult(m_audioClient->SetClientProperties(&audioProps));
auto hr = m_audioClient->SetClientProperties(&audioProps);
LOGI() << "survived m_audioClient->SetClientProperties(&audioProps)";
check_hresult(hr);
LOGI() << "survived check_hresult(m_audioClient->SetClientProperties(&audioProps));";
// If application already has a preferred source format available,
// it can test whether the format is supported by the device:
@ -304,7 +409,10 @@ HRESULT WasapiAudioClient::configureDeviceInternal() noexcept
// This sample opens the device is shared mode so we need to find the supported WAVEFORMATEX mix format
LOGI() << "WASAPI: Getting device mix format";
check_hresult(m_audioClient->GetMixFormat(m_mixFormat.put()));
hr = m_audioClient->GetMixFormat(m_mixFormat.put());
LOGI() << "survived m_audioClient->GetMixFormat(m_mixFormat.put())";
check_hresult(hr);
LOGI() << "survived check_hersult(m_audioClient->GetMixFormat(m_mixFormat.put()))";
LOGI() << "WASAPI: Mix format after getting from audio client:";
logWAVEFORMATEX(m_mixFormat.get());
@ -320,8 +428,10 @@ HRESULT WasapiAudioClient::configureDeviceInternal() noexcept
logWAVEFORMATEX(m_mixFormat.get());
if (m_useClosestSupportedFormat) {
LOGI() << "m_useClosestSupportedFormat";
unique_cotaskmem_ptr<WAVEFORMATEX> closestSupported;
m_audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, m_mixFormat.get(), closestSupported.put());
LOGI() << "survived m_audioClient->IsFormatSupported";
logWAVEFORMATEX(closestSupported.get());
m_mixFormat = std::move(closestSupported);
@ -331,16 +441,22 @@ HRESULT WasapiAudioClient::configureDeviceInternal() noexcept
LOGI() << "WASAPI: Getting shared mode engine period";
// The wfx parameter below is optional (Its needed only for MATCH_FORMAT clients). Otherwise, wfx will be assumed
// to be the current engine format based on the processing mode for this stream
check_hresult(m_audioClient->GetSharedModeEnginePeriod(m_mixFormat.get(), &m_defaultPeriodInFrames,
&m_fundamentalPeriodInFrames,
&m_minPeriodInFrames, &m_maxPeriodInFrames));
auto h = m_audioClient->GetSharedModeEnginePeriod(m_mixFormat.get(), &m_defaultPeriodInFrames,
&m_fundamentalPeriodInFrames,
&m_minPeriodInFrames, &m_maxPeriodInFrames);
LOGI() << "survived m_audioClient->GetSharedModeEnginePeriod";
check_hresult(h);
LOGI() << "survived check_hresult(m_audioClient->GetSharedModeEnginePeriod)";
}
LOGI() << "WASAPI: Device successfully configured";
return S_OK;
} catch (...) {
return to_hresult();
EEEE_CATCH;
auto r = to_hresult();
LOGI() << "survived to_hresult";
return r;
}
}
@ -352,6 +468,7 @@ HRESULT WasapiAudioClient::configureDeviceInternal() noexcept
//
void WasapiAudioClient::validateBufferValue()
{
EEEEE;
if (!m_isHWOffload) {
// If we aren't using HW Offload, set this to 0 to use the default value
m_hnsBufferDuration = 0;
@ -361,7 +478,12 @@ void WasapiAudioClient::validateBufferValue()
REFERENCE_TIME hnsMinBufferDuration;
REFERENCE_TIME hnsMaxBufferDuration;
check_hresult(m_audioClient->GetBufferSizeLimits(m_mixFormat.get(), true, &hnsMinBufferDuration, &hnsMaxBufferDuration));
auto hr = m_audioClient->GetBufferSizeLimits(m_mixFormat.get(), true, &hnsMinBufferDuration, &hnsMaxBufferDuration);
LOGI() << "survived m_audioClient->GetBufferSizeLimits(m_mixFormat.get(), true, &hnsMinBufferDuration, &hnsMaxBufferDuration)";
check_hresult(hr);
LOGI() <<
"survived check_hresult(m_audioClient->GetBufferSizeLimits(m_mixFormat.get(), true, &hnsMinBufferDuration, &hnsMaxBufferDuration))";
if (m_hnsBufferDuration < hnsMinBufferDuration) {
// using MINIMUM size instead
m_hnsBufferDuration = hnsMinBufferDuration;
@ -379,24 +501,31 @@ void WasapiAudioClient::validateBufferValue()
//
void WasapiAudioClient::startPlayback() noexcept
{
EEEEE;
try {
EEEE_TRY;
switch (m_deviceState) {
// We should be stopped if the user stopped playback, or we should be
// initialized if this is the first time through getting ready to playback.
case DeviceState::Stopped:
case DeviceState::Initialized:
case DeviceState::Initialized: {
setStateAndNotify(DeviceState::Starting, S_OK);
check_hresult(MFPutWorkItem2(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, 0, &m_startPlaybackCallback, nullptr));
auto hr = MFPutWorkItem2(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, 0, &m_startPlaybackCallback, nullptr);
LOGI() << "survived MFPutWorkItem2(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, 0, &m_startPlaybackCallback, nullptr)";
check_hresult(hr);
LOGI() << "survived check_hresult(MFPutWorkItem2(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, 0, &m_startPlaybackCallback, nullptr))";
break;
}
default:
// Otherwise something else happened
throw hresult_error(E_FAIL);
}
} catch (...) {
EEEE_CATCH;
hresult error = to_hresult();
LOGI() << "survived to_hresult";
setStateAndNotify(DeviceState::Error, error);
LOGI() << "survived setStateAndNotify";
SetEvent(m_clientFailedToStartEvent);
}
}
@ -408,24 +537,40 @@ void WasapiAudioClient::startPlayback() noexcept
//
HRESULT WasapiAudioClient::onStartPlayback(IMFAsyncResult*) noexcept
{
EEEEE;
try {
EEEE_TRY;
// Pre-Roll the buffer with silence
onAudioSampleRequested(true);
LOGI() << "survived onAurioSampleRequested";
// Set the initial volume.
//SetAudioClientChannelVolume();
// Actually start the playback
check_hresult(m_audioClient->Start());
auto hr = m_audioClient->Start();
LOGI() << "survived m_audioClient->Start()";
check_hresult(hr);
LOGI() << "survivied check_hresult(m_audioClient->Start());";
setStateAndNotify(DeviceState::Playing, S_OK);
check_hresult(MFPutWaitingWorkItem(m_sampleReadyEvent.get(), 0, m_sampleReadyAsyncResult.get(), &m_sampleReadyKey));
LOGI() << "survived setStateAndNotify";
hr = MFPutWaitingWorkItem(m_sampleReadyEvent.get(), 0, m_sampleReadyAsyncResult.get(), &m_sampleReadyKey);
LOGI() << "survived MFPutWaitingWorkItem(m_sampleReadyEvent.get(), 0, m_sampleReadyAsyncResult.get(), &m_sampleReadyKey)";
check_hresult(hr);
LOGI() <<
"survived check_hresult(MFPutWaitingWorkItem(m_sampleReadyEvent.get(), 0, m_sampleReadyAsyncResult.get(), &m_sampleReadyKey))";
SetEvent(m_clientStartedEvent);
return S_OK;
} catch (...) {
setStateAndNotify(DeviceState::Error, to_hresult());
EEEE_CATCH;
hresult error = to_hresult();
LOGI() << "survived to_hresult";
setStateAndNotify(DeviceState::Error, error);
LOGI() << "survived setStateAndNotify";
SetEvent(m_clientFailedToStartEvent);
@ -441,6 +586,7 @@ HRESULT WasapiAudioClient::onStartPlayback(IMFAsyncResult*) noexcept
//
HRESULT WasapiAudioClient::stopPlaybackAsync() noexcept
{
EEEEE;
if ((m_deviceState != DeviceState::Playing)
&& (m_deviceState != DeviceState::Paused)
&& (m_deviceState != DeviceState::Error)) {
@ -459,6 +605,7 @@ HRESULT WasapiAudioClient::stopPlaybackAsync() noexcept
//
HRESULT WasapiAudioClient::onStopPlayback(IMFAsyncResult*)
{
EEEEE;
// Stop playback by cancelling Work Item
// Cancel the queued work item (if any)
@ -489,7 +636,9 @@ HRESULT WasapiAudioClient::onStopPlayback(IMFAsyncResult*)
//
HRESULT WasapiAudioClient::onSampleReady(IMFAsyncResult*)
{
EEEEE;
try {
EEEE_TRY;
onAudioSampleRequested(false);
// Re-queue work item for next sample
@ -499,6 +648,7 @@ HRESULT WasapiAudioClient::onSampleReady(IMFAsyncResult*)
return S_OK;
} catch (...) {
EEEE_CATCH;
hresult error = to_hresult();
setStateAndNotify(DeviceState::Error, error);
return error;
@ -512,7 +662,9 @@ HRESULT WasapiAudioClient::onSampleReady(IMFAsyncResult*)
//
void WasapiAudioClient::onAudioSampleRequested(bool IsSilence)
{
EEEEE;
try {
EEEE_TRY;
auto guard = slim_lock_guard(m_lock);
// Get padding in existing buffer
@ -546,6 +698,7 @@ void WasapiAudioClient::onAudioSampleRequested(bool IsSilence)
}
catch (hresult_error const& error)
{
EEEE_CATCH;
if (error.code() != AUDCLNT_E_RESOURCES_INVALIDATED) {
throw;
}
@ -564,6 +717,7 @@ void WasapiAudioClient::onAudioSampleRequested(bool IsSilence)
void WasapiAudioClient::getSamples(uint32_t framesAvailable)
{
EEEEE;
uint8_t* data;
uint32_t actualFramesToRead = framesAvailable;
@ -587,6 +741,7 @@ void WasapiAudioClient::setState(const DeviceState newState)
void WasapiAudioClient::setStateAndNotify(const DeviceState newState, hresult resultCode)
{
LOGI() << "entering";
if (m_deviceState == newState) {
return;
}
@ -674,6 +829,7 @@ void WasapiAudioClient::setStateAndNotify(const DeviceState newState, hresult re
break;
case S_OK:
errMsg = "S_OK";
break;
default: