diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e12309cd2..12bd84a3f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -539,6 +539,10 @@ add_library(core STATIC hle/service/audio/audio_renderer_manager.h hle/service/audio/audio_renderer.cpp hle/service/audio/audio_renderer.h + hle/service/audio/audio_snoop_manager.cpp + hle/service/audio/audio_snoop_manager.h + hle/service/audio/audio_system_manager.cpp + hle/service/audio/audio_system_manager.h hle/service/audio/audio.cpp hle/service/audio/audio.h hle/service/audio/codecctl.cpp diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp index 52861eb5c..d27a9c8db 100644 --- a/src/core/hle/service/audio/audio.cpp +++ b/src/core/hle/service/audio/audio.cpp @@ -10,6 +10,8 @@ #include "core/hle/service/audio/audio_in_manager.h" #include "core/hle/service/audio/audio_out_manager.h" #include "core/hle/service/audio/audio_renderer_manager.h" +#include "core/hle/service/audio/audio_snoop_manager.h" +#include "core/hle/service/audio/audio_system_manager.h" #include "core/hle/service/audio/codecctl.h" #include "core/hle/service/audio/final_output_recorder_manager.h" #include "core/hle/service/audio/final_output_recorder_manager_for_applet.h" @@ -50,9 +52,12 @@ void LoopProcess(Core::System& system) { // Debug service server_manager->RegisterNamedService("auddebug", std::make_shared(system)); - // System-level audio services - server_manager->RegisterNamedService("aud:a", std::make_shared(system)); // System version of audctl - server_manager->RegisterNamedService("aud:d", std::make_shared(system, "aud:d")); // System device service + // Audio snoop service (auddev) + server_manager->RegisterNamedService("auddev", std::make_shared(system)); + + // System-level audio services [11.0.0+] + server_manager->RegisterNamedService("aud:a", std::make_shared(system)); // System manager for applet + server_manager->RegisterNamedService("aud:d", std::make_shared(system)); // System manager for debugger ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp index 2ff2a4bd0..cd533a314 100644 --- a/src/core/hle/service/audio/audio_controller.cpp +++ b/src/core/hle/service/audio/audio_controller.cpp @@ -69,6 +69,11 @@ IAudioController::IAudioController(Core::System& system_) {10105, D<&IAudioController::BindAudioOutputChannelCountUpdateEventForPlayReport>, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {10106, D<&IAudioController::GetDefaultAudioOutputTargetForPlayReport>, "GetDefaultAudioOutputTargetForPlayReport"}, {50000, D<&IAudioController::SetAnalogInputBoostGainForPrototyping>, "SetAnalogInputBoostGainForPrototyping"}, + {50001, D<&IAudioController::OverrideDefaultTargetForDebug>, "OverrideDefaultTargetForDebug"}, // [19.0.0-19.0.1] + {50003, D<&IAudioController::SetForceOverrideExternalDeviceNameForDebug>, "SetForceOverrideExternalDeviceNameForDebug"}, // [19.0.0+] + {50004, D<&IAudioController::ClearForceOverrideExternalDeviceNameForDebug>, "ClearForceOverrideExternalDeviceNameForDebug"}, // [19.0.0+] + {5000, nullptr, "Unknown5000"}, // [19.0.0+] + {10200, nullptr, "Unknown10200"}, // [20.0.0+] }; // clang-format on @@ -328,8 +333,9 @@ Result IAudioController::IsHearingProtectionSafeguardMonitoringOutputForDebug(Ou R_SUCCEED(); } -Result IAudioController::GetSystemInformationForDebug(OutLargeData out_info) { +Result IAudioController::GetSystemInformationForDebug(OutLargeData, BufferAttr_HipcMapAlias> out_info) { LOG_WARNING(Audio, "(STUBBED) called"); + std::memset(out_info->data(), 0, out_info->size()); R_SUCCEED(); } @@ -381,4 +387,19 @@ Result IAudioController::SetAnalogInputBoostGainForPrototyping(f32 gain) { R_SUCCEED(); } +Result IAudioController::OverrideDefaultTargetForDebug(u32 target) { + LOG_WARNING(Audio, "(STUBBED) called, target={}", target); + R_SUCCEED(); +} + +Result IAudioController::SetForceOverrideExternalDeviceNameForDebug(InLargeData, BufferAttr_HipcMapAlias> device_name) { + LOG_WARNING(Audio, "(STUBBED) called, device_name size={}", device_name->size()); + R_SUCCEED(); +} + +Result IAudioController::ClearForceOverrideExternalDeviceNameForDebug() { + LOG_WARNING(Audio, "(STUBBED) called"); + R_SUCCEED(); +} + } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_controller.h b/src/core/hle/service/audio/audio_controller.h index 198cbcc7c..36ba409c0 100644 --- a/src/core/hle/service/audio/audio_controller.h +++ b/src/core/hle/service/audio/audio_controller.h @@ -77,7 +77,7 @@ private: Result SetHearingProtectionSafeguardEnabled(bool is_enabled); Result IsHearingProtectionSafeguardEnabled(Out out_is_enabled); Result IsHearingProtectionSafeguardMonitoringOutputForDebug(Out out_is_monitoring); - Result GetSystemInformationForDebug(OutLargeData out_info); + Result GetSystemInformationForDebug(OutLargeData, BufferAttr_HipcMapAlias> out_info); Result SetVolumeButtonLongPressTime(u64 long_press_time); Result SetNativeVolumeForDebug(f32 native_volume); Result NotifyAudioOutputTargetForPlayReport(u32 target); @@ -87,6 +87,9 @@ private: Result BindAudioOutputTargetUpdateEventForPlayReport(OutCopyHandle out_event); Result GetDefaultAudioOutputTargetForPlayReport(Out out_target); Result SetAnalogInputBoostGainForPrototyping(f32 gain); + Result OverrideDefaultTargetForDebug(u32 target); // [19.0.0-19.0.1] + Result SetForceOverrideExternalDeviceNameForDebug(InLargeData, BufferAttr_HipcMapAlias> device_name); // [19.0.0+] + Result ClearForceOverrideExternalDeviceNameForDebug(); // [19.0.0+] KernelHelpers::ServiceContext service_context; diff --git a/src/core/hle/service/audio/audio_device.cpp b/src/core/hle/service/audio/audio_device.cpp index 735075d19..158a9b2a9 100644 --- a/src/core/hle/service/audio/audio_device.cpp +++ b/src/core/hle/service/audio/audio_device.cpp @@ -31,6 +31,12 @@ IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u {12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"}, {13, D<&IAudioDevice::GetActiveAudioOutputDeviceName>, "GetActiveAudioOutputDeviceName"}, {14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"}, + {15, D<&IAudioDevice::AcquireAudioInputDeviceNotification>, "AcquireAudioInputDeviceNotification"}, // [17.0.0+] + {16, D<&IAudioDevice::ReleaseAudioInputDeviceNotification>, "ReleaseAudioInputDeviceNotification"}, // [17.0.0+] + {17, D<&IAudioDevice::AcquireAudioOutputDeviceNotification>, "AcquireAudioOutputDeviceNotification"}, // [17.0.0+] + {18, D<&IAudioDevice::ReleaseAudioOutputDeviceNotification>, "ReleaseAudioOutputDeviceNotification"}, // [17.0.0+] + {19, D<&IAudioDevice::SetAudioDeviceOutputVolumeAutoTuneEnabled>, "SetAudioDeviceOutputVolumeAutoTuneEnabled"}, // [18.0.0+] + {20, D<&IAudioDevice::IsAudioDeviceOutputVolumeAutoTuneEnabled>, "IsAudioDeviceOutputVolumeAutoTuneEnabled"}, // [18.0.0+] }; RegisterHandlers(functions); @@ -173,4 +179,37 @@ Result IAudioDevice::ListAudioOutputDeviceName( R_SUCCEED(); } +Result IAudioDevice::AcquireAudioInputDeviceNotification(OutCopyHandle out_event) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + *out_event = &event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IAudioDevice::ReleaseAudioInputDeviceNotification(InCopyHandle notification_event) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IAudioDevice::AcquireAudioOutputDeviceNotification(OutCopyHandle out_event) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + *out_event = &event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IAudioDevice::ReleaseAudioOutputDeviceNotification(InCopyHandle notification_event) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IAudioDevice::SetAudioDeviceOutputVolumeAutoTuneEnabled(bool enabled) { + LOG_WARNING(Service_Audio, "(STUBBED) called, enabled={}", enabled); + R_SUCCEED(); +} + +Result IAudioDevice::IsAudioDeviceOutputVolumeAutoTuneEnabled(Out out_enabled) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + *out_enabled = false; + R_SUCCEED(); +} + } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_device.h b/src/core/hle/service/audio/audio_device.h index 8fd4f1269..9dfc22f28 100644 --- a/src/core/hle/service/audio/audio_device.h +++ b/src/core/hle/service/audio/audio_device.h @@ -53,6 +53,12 @@ private: Result ListAudioOutputDeviceName( OutArray out_names, Out out_count); + Result AcquireAudioInputDeviceNotification(OutCopyHandle out_event); // [17.0.0+] + Result ReleaseAudioInputDeviceNotification(InCopyHandle notification_event); // [17.0.0+] + Result AcquireAudioOutputDeviceNotification(OutCopyHandle out_event); // [17.0.0+] + Result ReleaseAudioOutputDeviceNotification(InCopyHandle notification_event); // [17.0.0+] + Result SetAudioDeviceOutputVolumeAutoTuneEnabled(bool enabled); // [18.0.0+] + Result IsAudioDeviceOutputVolumeAutoTuneEnabled(Out out_enabled); // [18.0.0+] KernelHelpers::ServiceContext service_context; std::unique_ptr impl; diff --git a/src/core/hle/service/audio/audio_snoop_manager.cpp b/src/core/hle/service/audio/audio_snoop_manager.cpp new file mode 100644 index 000000000..df5061327 --- /dev/null +++ b/src/core/hle/service/audio/audio_snoop_manager.cpp @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/audio/audio_snoop_manager.h" +#include "core/hle/service/cmif_serialization.h" +#include +#include + +namespace Service::Audio { + +IAudioSnoopManager::IAudioSnoopManager(Core::System& system_) + : ServiceFramework{system_, "auddev"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IAudioSnoopManager::EnableDspUsageMeasurement>, "EnableDspUsageMeasurement"}, // [6.0.0-16.1.0] / [17.0.0+] GetDspStatistics + {1, D<&IAudioSnoopManager::DisableDspUsageMeasurement>, "DisableDspUsageMeasurement"}, // [6.0.0-16.1.0] / [20.0.0+] GetAppletStateSummaries + {2, D<&IAudioSnoopManager::SetDspStatisticsParameter>, "SetDspStatisticsParameter"}, // [20.0.0+] + {3, D<&IAudioSnoopManager::GetDspStatisticsParameter>, "GetDspStatisticsParameter"}, // [20.0.0+] + {6, D<&IAudioSnoopManager::GetDspUsage>, "GetDspUsage"}, // [6.0.0-16.1.0] + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAudioSnoopManager::~IAudioSnoopManager() = default; + +Result IAudioSnoopManager::EnableDspUsageMeasurement() { + LOG_INFO(Service_Audio, "called"); + + // [6.0.0-16.1.0] EnableDspUsageMeasurement + dsp_usage_measurement_enabled = true; + + R_SUCCEED(); +} + +Result IAudioSnoopManager::GetDspStatistics(Out out_statistics) { + LOG_INFO(Service_Audio, "called"); + + // [17.0.0+] GetDspStatistics + *out_statistics = dsp_statistics; + + R_SUCCEED(); +} + +Result IAudioSnoopManager::DisableDspUsageMeasurement() { + LOG_INFO(Service_Audio, "called"); + + // [6.0.0-16.1.0] DisableDspUsageMeasurement + dsp_usage_measurement_enabled = false; + + R_SUCCEED(); +} + +Result IAudioSnoopManager::GetAppletStateSummaries(OutLargeData, BufferAttr_HipcMapAlias> out_summaries) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + + // [20.0.0+] GetAppletStateSummaries + // This function returns applet state summaries in a buffer + // Since we don't have real applet state tracking, return empty data + std::memset(out_summaries->data(), 0, out_summaries->size()); + + R_SUCCEED(); +} + +Result IAudioSnoopManager::SetDspStatisticsParameter(InLargeData, BufferAttr_HipcMapAlias> parameter) { + LOG_INFO(Service_Audio, "called with parameter size {}", parameter->size()); + + // [20.0.0+] SetDspStatisticsParameter + // Copy the parameter data to our internal buffer + const size_t copy_size = std::min(parameter->size(), dsp_statistics_parameter.size()); + std::memcpy(dsp_statistics_parameter.data(), parameter->data(), copy_size); + + R_SUCCEED(); +} + +Result IAudioSnoopManager::GetDspStatisticsParameter(OutLargeData, BufferAttr_HipcMapAlias> out_parameter) { + LOG_INFO(Service_Audio, "called"); + + // [20.0.0+] GetDspStatisticsParameter + // Return the stored parameter data + const size_t copy_size = std::min(out_parameter->size(), dsp_statistics_parameter.size()); + std::memcpy(out_parameter->data(), dsp_statistics_parameter.data(), copy_size); + + R_SUCCEED(); +} + +Result IAudioSnoopManager::GetDspUsage(Out out_usage) { + LOG_INFO(Service_Audio, "called"); + + // [6.0.0-16.1.0] GetDspUsage + *out_usage = dsp_usage; + + R_SUCCEED(); +} + +} // namespace Service::Audio \ No newline at end of file diff --git a/src/core/hle/service/audio/audio_snoop_manager.h b/src/core/hle/service/audio/audio_snoop_manager.h new file mode 100644 index 000000000..661173256 --- /dev/null +++ b/src/core/hle/service/audio/audio_snoop_manager.h @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::Audio { + +class IAudioSnoopManager final : public ServiceFramework { +public: + explicit IAudioSnoopManager(Core::System& system_); + ~IAudioSnoopManager() override; + +private: + // [6.0.0-16.1.0] EnableDspUsageMeasurement / [17.0.0+] GetDspStatistics + Result EnableDspUsageMeasurement(); + Result GetDspStatistics(Out out_statistics); + + // [6.0.0-16.1.0] DisableDspUsageMeasurement / [20.0.0+] GetAppletStateSummaries + Result DisableDspUsageMeasurement(); + Result GetAppletStateSummaries(OutLargeData, BufferAttr_HipcMapAlias> out_summaries); + + // [20.0.0+] SetDspStatisticsParameter + Result SetDspStatisticsParameter(InLargeData, BufferAttr_HipcMapAlias> parameter); + + // [20.0.0+] GetDspStatisticsParameter + Result GetDspStatisticsParameter(OutLargeData, BufferAttr_HipcMapAlias> out_parameter); + + // [6.0.0-16.1.0] GetDspUsage + Result GetDspUsage(Out out_usage); + + // State variables + bool dsp_usage_measurement_enabled{false}; + u64 dsp_statistics{0}; + u64 dsp_usage{0}; + std::array dsp_statistics_parameter{}; +}; + +} // namespace Service::Audio \ No newline at end of file diff --git a/src/core/hle/service/audio/audio_system_manager.cpp b/src/core/hle/service/audio/audio_system_manager.cpp new file mode 100644 index 000000000..f91fa297d --- /dev/null +++ b/src/core/hle/service/audio/audio_system_manager.cpp @@ -0,0 +1,174 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/audio/audio_system_manager.h" +#include "core/hle/service/cmif_serialization.h" +#include +#include + +namespace Service::Audio { + +// IAudioSystemManagerForApplet implementation +IAudioSystemManagerForApplet::IAudioSystemManagerForApplet(Core::System& system_) + : ServiceFramework{system_, "aud:a"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IAudioSystemManagerForApplet::RegisterAppletResourceUserId>, "RegisterAppletResourceUserId"}, + {1, D<&IAudioSystemManagerForApplet::UnregisterAppletResourceUserId>, "UnregisterAppletResourceUserId"}, + {2, D<&IAudioSystemManagerForApplet::RequestSuspendAudio>, "RequestSuspendAudio"}, + {3, D<&IAudioSystemManagerForApplet::RequestResumeAudio>, "RequestResumeAudio"}, + {4, D<&IAudioSystemManagerForApplet::GetAudioOutputProcessMasterVolume>, "GetAudioOutputProcessMasterVolume"}, + {5, D<&IAudioSystemManagerForApplet::SetAudioOutputProcessMasterVolume>, "SetAudioOutputProcessMasterVolume"}, + {6, D<&IAudioSystemManagerForApplet::GetAudioInputProcessMasterVolume>, "GetAudioInputProcessMasterVolume"}, + {7, D<&IAudioSystemManagerForApplet::SetAudioInputProcessMasterVolume>, "SetAudioInputProcessMasterVolume"}, + {8, D<&IAudioSystemManagerForApplet::GetAudioOutputProcessRecordVolume>, "GetAudioOutputProcessRecordVolume"}, + {9, D<&IAudioSystemManagerForApplet::SetAudioOutputProcessRecordVolume>, "SetAudioOutputProcessRecordVolume"}, + {10, D<&IAudioSystemManagerForApplet::GetAppletStateSummaries>, "GetAppletStateSummaries"}, // [18.0.0-19.0.1] + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAudioSystemManagerForApplet::~IAudioSystemManagerForApplet() = default; + +Result IAudioSystemManagerForApplet::RegisterAppletResourceUserId(u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + registered_applets[applet_resource_user_id] = true; + // Set default volumes + applet_output_volumes[applet_resource_user_id] = 1.0f; + applet_input_volumes[applet_resource_user_id] = 1.0f; + applet_record_volumes[applet_resource_user_id] = 1.0f; + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::UnregisterAppletResourceUserId(u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + registered_applets.erase(applet_resource_user_id); + applet_output_volumes.erase(applet_resource_user_id); + applet_input_volumes.erase(applet_resource_user_id); + applet_record_volumes.erase(applet_resource_user_id); + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::RequestSuspendAudio(u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + // Mark as suspended for this applet + if (registered_applets.find(applet_resource_user_id) != registered_applets.end()) { + registered_applets[applet_resource_user_id] = false; + } + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::RequestResumeAudio(u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + // Mark as resumed for this applet + if (registered_applets.find(applet_resource_user_id) != registered_applets.end()) { + registered_applets[applet_resource_user_id] = true; + } + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::GetAudioOutputProcessMasterVolume(Out out_volume, u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + const auto it = applet_output_volumes.find(applet_resource_user_id); + *out_volume = (it != applet_output_volumes.end()) ? it->second : 1.0f; + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::SetAudioOutputProcessMasterVolume(f32 volume, u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, volume={}, applet_resource_user_id={:#x}", volume, applet_resource_user_id); + + applet_output_volumes[applet_resource_user_id] = std::clamp(volume, 0.0f, 1.0f); + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::GetAudioInputProcessMasterVolume(Out out_volume, u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + const auto it = applet_input_volumes.find(applet_resource_user_id); + *out_volume = (it != applet_input_volumes.end()) ? it->second : 1.0f; + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::SetAudioInputProcessMasterVolume(f32 volume, u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, volume={}, applet_resource_user_id={:#x}", volume, applet_resource_user_id); + + applet_input_volumes[applet_resource_user_id] = std::clamp(volume, 0.0f, 1.0f); + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::GetAudioOutputProcessRecordVolume(Out out_volume, u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + const auto it = applet_record_volumes.find(applet_resource_user_id); + *out_volume = (it != applet_record_volumes.end()) ? it->second : 1.0f; + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::SetAudioOutputProcessRecordVolume(f32 volume, u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, volume={}, applet_resource_user_id={:#x}", volume, applet_resource_user_id); + + applet_record_volumes[applet_resource_user_id] = std::clamp(volume, 0.0f, 1.0f); + + R_SUCCEED(); +} + +Result IAudioSystemManagerForApplet::GetAppletStateSummaries(OutLargeData, BufferAttr_HipcMapAlias> out_summaries) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + + // [18.0.0-19.0.1] GetAppletStateSummaries + // This function returns applet state summaries in a buffer + // Since we don't have real applet state tracking, return empty data + std::memset(out_summaries->data(), 0, out_summaries->size()); + + R_SUCCEED(); +} + +// IAudioSystemManagerForDebugger implementation +IAudioSystemManagerForDebugger::IAudioSystemManagerForDebugger(Core::System& system_) + : ServiceFramework{system_, "aud:d"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IAudioSystemManagerForDebugger::RequestSuspendAudioForDebug>, "RequestSuspendAudioForDebug"}, + {1, D<&IAudioSystemManagerForDebugger::RequestResumeAudioForDebug>, "RequestResumeAudioForDebug"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAudioSystemManagerForDebugger::~IAudioSystemManagerForDebugger() = default; + +Result IAudioSystemManagerForDebugger::RequestSuspendAudioForDebug(u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + suspended_applets[applet_resource_user_id] = true; + + R_SUCCEED(); +} + +Result IAudioSystemManagerForDebugger::RequestResumeAudioForDebug(u64 applet_resource_user_id) { + LOG_INFO(Service_Audio, "called, applet_resource_user_id={:#x}", applet_resource_user_id); + + suspended_applets[applet_resource_user_id] = false; + + R_SUCCEED(); +} + +} // namespace Service::Audio \ No newline at end of file diff --git a/src/core/hle/service/audio/audio_system_manager.h b/src/core/hle/service/audio/audio_system_manager.h new file mode 100644 index 000000000..3e770dc2b --- /dev/null +++ b/src/core/hle/service/audio/audio_system_manager.h @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::Audio { + +// This is "nn::audio::detail::IAudioSystemManagerForApplet" added with [11.0.0+] +class IAudioSystemManagerForApplet final : public ServiceFramework { +public: + explicit IAudioSystemManagerForApplet(Core::System& system_); + ~IAudioSystemManagerForApplet() override; + +private: + Result RegisterAppletResourceUserId(u64 applet_resource_user_id); + Result UnregisterAppletResourceUserId(u64 applet_resource_user_id); + Result RequestSuspendAudio(u64 applet_resource_user_id); + Result RequestResumeAudio(u64 applet_resource_user_id); + Result GetAudioOutputProcessMasterVolume(Out out_volume, u64 applet_resource_user_id); + Result SetAudioOutputProcessMasterVolume(f32 volume, u64 applet_resource_user_id); + Result GetAudioInputProcessMasterVolume(Out out_volume, u64 applet_resource_user_id); + Result SetAudioInputProcessMasterVolume(f32 volume, u64 applet_resource_user_id); + Result GetAudioOutputProcessRecordVolume(Out out_volume, u64 applet_resource_user_id); + Result SetAudioOutputProcessRecordVolume(f32 volume, u64 applet_resource_user_id); + Result GetAppletStateSummaries(OutLargeData, BufferAttr_HipcMapAlias> out_summaries); // [18.0.0-19.0.1] + + // State variables + std::map registered_applets; + std::map applet_output_volumes; + std::map applet_input_volumes; + std::map applet_record_volumes; +}; + +// This is "nn::audio::detail::IAudioSystemManagerForDebugger" added with [11.0.0+] +class IAudioSystemManagerForDebugger final : public ServiceFramework { +public: + explicit IAudioSystemManagerForDebugger(Core::System& system_); + ~IAudioSystemManagerForDebugger() override; + +private: + Result RequestSuspendAudioForDebug(u64 applet_resource_user_id); + Result RequestResumeAudioForDebug(u64 applet_resource_user_id); + + // State variables + std::map suspended_applets; +}; + +} // namespace Service::Audio \ No newline at end of file