From 238e8282b2a0f1eb9f44f4a26bb88ecc7db286cb Mon Sep 17 00:00:00 2001 From: Zephyron Date: Sat, 24 May 2025 16:39:15 +1000 Subject: [PATCH] hle/service/audio: Implement missing audio services and functions - Add complete IAudioController implementation with 32 missing functions: * Volume control (GetTargetVolume, SetTargetVolume, etc.) * Mute control (IsTargetMute, SetTargetMute, etc.) * Target management (SetDefaultTarget, GetDefaultTarget, etc.) * Play report functions (10000+ series command IDs) * Hearing protection safeguard functions * Debug and system functions - Add new audio services: * codecctl - Codec controller service with 13 functions * auddebug - Audio debug service placeholder * Device suspend/resume services (audout:d, audin:d, audrec:d, audren:d) * System audio services (aud:a, aud:d) * Applet audio services (audout:a, audin:a, audren:a) - Update IAudioDevice with missing functions: * GetAudioSystemMasterVolumeSetting * GetActiveAudioOutputDeviceName * Fix function ID mappings to match official documentation - Register all services in main audio LoopProcess function - Update CMakeLists.txt with new source files All implementations follow the official Switch audio services documentation from switchbrew.org and provide appropriate stub implementations with sensible default values for enhanced game compatibility. Signed-off-by: Zephyron --- src/core/CMakeLists.txt | 6 + src/core/hle/service/audio/audio.cpp | 41 ++- .../hle/service/audio/audio_controller.cpp | 287 +++++++++++++++--- src/core/hle/service/audio/audio_controller.h | 38 +++ src/core/hle/service/audio/audio_debug.cpp | 15 + src/core/hle/service/audio/audio_debug.h | 19 ++ src/core/hle/service/audio/audio_device.cpp | 19 +- src/core/hle/service/audio/audio_device.h | 4 + .../service/audio/audio_device_service.cpp | 34 +++ .../hle/service/audio/audio_device_service.h | 21 ++ src/core/hle/service/audio/codecctl.cpp | 110 +++++++ src/core/hle/service/audio/codecctl.h | 40 +++ 12 files changed, 582 insertions(+), 52 deletions(-) create mode 100644 src/core/hle/service/audio/audio_debug.cpp create mode 100644 src/core/hle/service/audio/audio_debug.h create mode 100644 src/core/hle/service/audio/audio_device_service.cpp create mode 100644 src/core/hle/service/audio/audio_device_service.h create mode 100644 src/core/hle/service/audio/codecctl.cpp create mode 100644 src/core/hle/service/audio/codecctl.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cb46c8653..8f1234481 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -515,8 +515,12 @@ add_library(core STATIC hle/service/apm/apm_interface.h hle/service/audio/audio_controller.cpp hle/service/audio/audio_controller.h + hle/service/audio/audio_debug.cpp + hle/service/audio/audio_debug.h hle/service/audio/audio_device.cpp hle/service/audio/audio_device.h + hle/service/audio/audio_device_service.cpp + hle/service/audio/audio_device_service.h hle/service/audio/audio_in_manager.cpp hle/service/audio/audio_in_manager.h hle/service/audio/audio_in.cpp @@ -531,6 +535,8 @@ add_library(core STATIC hle/service/audio/audio_renderer.h hle/service/audio/audio.cpp hle/service/audio/audio.h + hle/service/audio/codecctl.cpp + hle/service/audio/codecctl.h hle/service/audio/errors.h hle/service/audio/final_output_recorder_manager_for_applet.cpp hle/service/audio/final_output_recorder_manager_for_applet.h diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp index 331176bf7..52861eb5c 100644 --- a/src/core/hle/service/audio/audio.cpp +++ b/src/core/hle/service/audio/audio.cpp @@ -1,12 +1,16 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" #include "core/hle/service/audio/audio.h" #include "core/hle/service/audio/audio_controller.h" +#include "core/hle/service/audio/audio_debug.h" +#include "core/hle/service/audio/audio_device_service.h" #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/codecctl.h" #include "core/hle/service/audio/final_output_recorder_manager.h" #include "core/hle/service/audio/final_output_recorder_manager_for_applet.h" #include "core/hle/service/audio/hardware_opus_decoder_manager.h" @@ -18,17 +22,38 @@ namespace Service::Audio { void LoopProcess(Core::System& system) { auto server_manager = std::make_unique(system); + // Main audio services server_manager->RegisterNamedService("audctl", std::make_shared(system)); server_manager->RegisterNamedService("audin:u", std::make_shared(system)); server_manager->RegisterNamedService("audout:u", std::make_shared(system)); - server_manager->RegisterNamedService( - "audrec:a", std::make_shared(system)); - server_manager->RegisterNamedService("audrec:u", - std::make_shared(system)); - server_manager->RegisterNamedService("audren:u", - std::make_shared(system)); - server_manager->RegisterNamedService("hwopus", - std::make_shared(system)); + server_manager->RegisterNamedService("audren:u", std::make_shared(system)); + server_manager->RegisterNamedService("hwopus", std::make_shared(system)); + + // Final output recorder services + server_manager->RegisterNamedService("audrec:a", std::make_shared(system)); + server_manager->RegisterNamedService("audrec:u", std::make_shared(system)); + + // Applet versions of audio services + server_manager->RegisterNamedService("audout:a", std::make_shared(system)); + server_manager->RegisterNamedService("audin:a", std::make_shared(system)); + server_manager->RegisterNamedService("audren:a", std::make_shared(system)); + + // Device suspend/resume services + server_manager->RegisterNamedService("audout:d", std::make_shared(system, "audout:d")); + server_manager->RegisterNamedService("audin:d", std::make_shared(system, "audin:d")); + server_manager->RegisterNamedService("audrec:d", std::make_shared(system, "audrec:d")); + server_manager->RegisterNamedService("audren:d", std::make_shared(system, "audren:d")); + + // Codec controller service + server_manager->RegisterNamedService("codecctl", std::make_shared(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 + 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 7a51d1023..2ff2a4bd0 100644 --- a/src/core/hle/service/audio/audio_controller.cpp +++ b/src/core/hle/service/audio/audio_controller.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "common/logging/log.h" @@ -14,60 +15,60 @@ IAudioController::IAudioController(Core::System& system_) : ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetTargetVolume"}, - {1, nullptr, "SetTargetVolume"}, + {0, D<&IAudioController::GetTargetVolume>, "GetTargetVolume"}, + {1, D<&IAudioController::SetTargetVolume>, "SetTargetVolume"}, {2, D<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"}, {3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"}, - {4, nullptr, "IsTargetMute"}, - {5, nullptr, "SetTargetMute"}, - {6, nullptr, "IsTargetConnected"}, - {7, nullptr, "SetDefaultTarget"}, - {8, nullptr, "GetDefaultTarget"}, + {4, D<&IAudioController::IsTargetMute>, "IsTargetMute"}, + {5, D<&IAudioController::SetTargetMute>, "SetTargetMute"}, + {6, D<&IAudioController::IsTargetConnected>, "IsTargetConnected"}, + {7, D<&IAudioController::SetDefaultTarget>, "SetDefaultTarget"}, + {8, D<&IAudioController::GetDefaultTarget>, "GetDefaultTarget"}, {9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"}, {10, D<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"}, - {11, nullptr, "SetForceMutePolicy"}, + {11, D<&IAudioController::SetForceMutePolicy>, "SetForceMutePolicy"}, {12, D<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"}, {13, D<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"}, {14, D<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"}, - {15, nullptr, "SetOutputTarget"}, - {16, nullptr, "SetInputTargetForceEnabled"}, + {15, D<&IAudioController::SetOutputTarget>, "SetOutputTarget"}, + {16, D<&IAudioController::SetInputTargetForceEnabled>, "SetInputTargetForceEnabled"}, {17, D<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"}, {18, D<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"}, - {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, - {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, - {21, nullptr, "GetAudioOutputTargetForPlayReport"}, + {19, D<&IAudioController::AcquireAudioVolumeUpdateEventForPlayReport>, "AcquireAudioVolumeUpdateEventForPlayReport"}, + {20, D<&IAudioController::AcquireAudioOutputDeviceUpdateEventForPlayReport>, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, + {21, D<&IAudioController::GetAudioOutputTargetForPlayReport>, "GetAudioOutputTargetForPlayReport"}, {22, D<&IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent>, "NotifyHeadphoneVolumeWarningDisplayedEvent"}, - {23, nullptr, "SetSystemOutputMasterVolume"}, - {24, nullptr, "GetSystemOutputMasterVolume"}, - {25, nullptr, "GetAudioVolumeDataForPlayReport"}, - {26, nullptr, "UpdateHeadphoneSettings"}, - {27, nullptr, "SetVolumeMappingTableForDev"}, - {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, - {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, + {23, D<&IAudioController::SetSystemOutputMasterVolume>, "SetSystemOutputMasterVolume"}, + {24, D<&IAudioController::GetSystemOutputMasterVolume>, "GetSystemOutputMasterVolume"}, + {25, D<&IAudioController::GetAudioVolumeDataForPlayReport>, "GetAudioVolumeDataForPlayReport"}, + {26, D<&IAudioController::UpdateHeadphoneSettings>, "UpdateHeadphoneSettings"}, + {27, D<&IAudioController::SetVolumeMappingTableForDev>, "SetVolumeMappingTableForDev"}, + {28, D<&IAudioController::GetAudioOutputChannelCountForPlayReport>, "GetAudioOutputChannelCountForPlayReport"}, + {29, D<&IAudioController::BindAudioOutputChannelCountUpdateEventForPlayReport>, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {30, D<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"}, {31, D<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"}, - {32, nullptr, "GetActiveOutputTarget"}, - {33, nullptr, "GetTargetDeviceInfo"}, + {32, D<&IAudioController::GetActiveOutputTarget>, "GetActiveOutputTarget"}, + {33, D<&IAudioController::GetTargetDeviceInfo>, "GetTargetDeviceInfo"}, {34, D<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"}, - {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, - {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, - {37, nullptr, "SetHearingProtectionSafeguardEnabled"}, - {38, nullptr, "IsHearingProtectionSafeguardEnabled"}, - {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"}, - {40, nullptr, "GetSystemInformationForDebug"}, - {41, nullptr, "SetVolumeButtonLongPressTime"}, - {42, nullptr, "SetNativeVolumeForDebug"}, - {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"}, - {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"}, - {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, - {10100, nullptr, "GetAudioVolumeDataForPlayReport"}, - {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"}, - {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"}, - {10103, nullptr, "GetAudioOutputTargetForPlayReport"}, - {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"}, - {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, - {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, - {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, + {35, D<&IAudioController::SetHearingProtectionSafeguardTimerRemainingTimeForDebug>, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, + {36, D<&IAudioController::GetHearingProtectionSafeguardTimerRemainingTimeForDebug>, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, + {37, D<&IAudioController::SetHearingProtectionSafeguardEnabled>, "SetHearingProtectionSafeguardEnabled"}, + {38, D<&IAudioController::IsHearingProtectionSafeguardEnabled>, "IsHearingProtectionSafeguardEnabled"}, + {39, D<&IAudioController::IsHearingProtectionSafeguardMonitoringOutputForDebug>, "IsHearingProtectionSafeguardMonitoringOutputForDebug"}, + {40, D<&IAudioController::GetSystemInformationForDebug>, "GetSystemInformationForDebug"}, + {41, D<&IAudioController::SetVolumeButtonLongPressTime>, "SetVolumeButtonLongPressTime"}, + {42, D<&IAudioController::SetNativeVolumeForDebug>, "SetNativeVolumeForDebug"}, + {10000, D<&IAudioController::NotifyAudioOutputTargetForPlayReport>, "NotifyAudioOutputTargetForPlayReport"}, + {10001, D<&IAudioController::NotifyAudioOutputChannelCountForPlayReport>, "NotifyAudioOutputChannelCountForPlayReport"}, + {10002, D<&IAudioController::NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport>, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, + {10100, D<&IAudioController::GetAudioVolumeDataForPlayReport>, "GetAudioVolumeDataForPlayReport"}, + {10101, D<&IAudioController::BindAudioVolumeUpdateEventForPlayReport>, "BindAudioVolumeUpdateEventForPlayReport"}, + {10102, D<&IAudioController::BindAudioOutputTargetUpdateEventForPlayReport>, "BindAudioOutputTargetUpdateEventForPlayReport"}, + {10103, D<&IAudioController::GetAudioOutputTargetForPlayReport>, "GetAudioOutputTargetForPlayReport"}, + {10104, D<&IAudioController::GetAudioOutputChannelCountForPlayReport>, "GetAudioOutputChannelCountForPlayReport"}, + {10105, D<&IAudioController::BindAudioOutputChannelCountUpdateEventForPlayReport>, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, + {10106, D<&IAudioController::GetDefaultAudioOutputTargetForPlayReport>, "GetDefaultAudioOutputTargetForPlayReport"}, + {50000, D<&IAudioController::SetAnalogInputBoostGainForPrototyping>, "SetAnalogInputBoostGainForPrototyping"}, }; // clang-format on @@ -176,4 +177,208 @@ Result IAudioController::AcquireTargetNotification( R_SUCCEED(); } +Result IAudioController::GetTargetVolume(Out out_target_volume) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_target_volume = 10; + R_SUCCEED(); +} + +Result IAudioController::SetTargetVolume(s32 target_volume) { + LOG_WARNING(Audio, "(STUBBED) called, target_volume={}", target_volume); + R_SUCCEED(); +} + +Result IAudioController::IsTargetMute(Out out_is_target_mute) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_is_target_mute = false; + R_SUCCEED(); +} + +Result IAudioController::SetTargetMute(bool is_target_mute) { + LOG_WARNING(Audio, "(STUBBED) called, is_target_mute={}", is_target_mute); + R_SUCCEED(); +} + +Result IAudioController::IsTargetConnected(Out out_is_target_connected) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_is_target_connected = true; + R_SUCCEED(); +} + +Result IAudioController::SetDefaultTarget(u32 target) { + LOG_WARNING(Audio, "(STUBBED) called, target={}", target); + R_SUCCEED(); +} + +Result IAudioController::GetDefaultTarget(Out out_target) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_target = 0; + R_SUCCEED(); +} + +Result IAudioController::SetForceMutePolicy(ForceMutePolicy force_mute_policy) { + LOG_WARNING(Audio, "(STUBBED) called, force_mute_policy={}", static_cast(force_mute_policy)); + R_SUCCEED(); +} + +Result IAudioController::SetOutputTarget(u32 target) { + LOG_WARNING(Audio, "(STUBBED) called, target={}", target); + R_SUCCEED(); +} + +Result IAudioController::SetInputTargetForceEnabled(bool is_force_enabled) { + LOG_WARNING(Audio, "(STUBBED) called, is_force_enabled={}", is_force_enabled); + R_SUCCEED(); +} + +Result IAudioController::AcquireAudioVolumeUpdateEventForPlayReport(OutCopyHandle out_event) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_event = ¬ification_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IAudioController::AcquireAudioOutputDeviceUpdateEventForPlayReport(OutCopyHandle out_event) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_event = ¬ification_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IAudioController::GetAudioOutputTargetForPlayReport(Out out_target) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_target = 0; + R_SUCCEED(); +} + +Result IAudioController::SetSystemOutputMasterVolume(f32 volume) { + LOG_INFO(Audio, "called, volume={}", volume); + R_SUCCEED(); +} + +Result IAudioController::GetSystemOutputMasterVolume(Out out_volume) { + LOG_INFO(Audio, "called"); + *out_volume = 1.0f; + R_SUCCEED(); +} + +Result IAudioController::GetAudioVolumeDataForPlayReport(Out out_volume_data) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_volume_data = 0; + R_SUCCEED(); +} + +Result IAudioController::UpdateHeadphoneSettings() { + LOG_WARNING(Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IAudioController::SetVolumeMappingTableForDev(InLargeData volume_mapping_table) { + LOG_WARNING(Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IAudioController::GetAudioOutputChannelCountForPlayReport(Out out_channel_count) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_channel_count = 2; + R_SUCCEED(); +} + +Result IAudioController::BindAudioOutputChannelCountUpdateEventForPlayReport(OutCopyHandle out_event) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_event = ¬ification_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IAudioController::GetActiveOutputTarget(Out out_target) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_target = 0; + R_SUCCEED(); +} + +Result IAudioController::GetTargetDeviceInfo(Out out_device_info, u32 target) { + LOG_WARNING(Audio, "(STUBBED) called, target={}", target); + *out_device_info = 0; + R_SUCCEED(); +} + +Result IAudioController::SetHearingProtectionSafeguardTimerRemainingTimeForDebug(u64 remaining_time) { + LOG_WARNING(Audio, "(STUBBED) called, remaining_time={}", remaining_time); + R_SUCCEED(); +} + +Result IAudioController::GetHearingProtectionSafeguardTimerRemainingTimeForDebug(Out out_remaining_time) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_remaining_time = 0; + R_SUCCEED(); +} + +Result IAudioController::SetHearingProtectionSafeguardEnabled(bool is_enabled) { + LOG_WARNING(Audio, "(STUBBED) called, is_enabled={}", is_enabled); + R_SUCCEED(); +} + +Result IAudioController::IsHearingProtectionSafeguardEnabled(Out out_is_enabled) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_is_enabled = false; + R_SUCCEED(); +} + +Result IAudioController::IsHearingProtectionSafeguardMonitoringOutputForDebug(Out out_is_monitoring) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_is_monitoring = false; + R_SUCCEED(); +} + +Result IAudioController::GetSystemInformationForDebug(OutLargeData out_info) { + LOG_WARNING(Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IAudioController::SetVolumeButtonLongPressTime(u64 long_press_time) { + LOG_WARNING(Audio, "(STUBBED) called, long_press_time={}", long_press_time); + R_SUCCEED(); +} + +Result IAudioController::SetNativeVolumeForDebug(f32 native_volume) { + LOG_WARNING(Audio, "(STUBBED) called, native_volume={}", native_volume); + R_SUCCEED(); +} + +Result IAudioController::NotifyAudioOutputTargetForPlayReport(u32 target) { + LOG_WARNING(Audio, "(STUBBED) called, target={}", target); + R_SUCCEED(); +} + +Result IAudioController::NotifyAudioOutputChannelCountForPlayReport(u32 channel_count) { + LOG_WARNING(Audio, "(STUBBED) called, channel_count={}", channel_count); + R_SUCCEED(); +} + +Result IAudioController::NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport() { + LOG_WARNING(Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IAudioController::BindAudioVolumeUpdateEventForPlayReport(OutCopyHandle out_event) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_event = ¬ification_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IAudioController::BindAudioOutputTargetUpdateEventForPlayReport(OutCopyHandle out_event) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_event = ¬ification_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IAudioController::GetDefaultAudioOutputTargetForPlayReport(Out out_target) { + LOG_WARNING(Audio, "(STUBBED) called"); + *out_target = 0; + R_SUCCEED(); +} + +Result IAudioController::SetAnalogInputBoostGainForPrototyping(f32 gain) { + LOG_WARNING(Audio, "(STUBBED) called, gain={}", gain); + 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 d37c4843e..198cbcc7c 100644 --- a/src/core/hle/service/audio/audio_controller.h +++ b/src/core/hle/service/audio/audio_controller.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -33,22 +34,59 @@ private: HighPower, }; + Result GetTargetVolume(Out out_target_volume); + Result SetTargetVolume(s32 target_volume); Result GetTargetVolumeMin(Out out_target_min_volume); Result GetTargetVolumeMax(Out out_target_max_volume); + Result IsTargetMute(Out out_is_target_mute); + Result SetTargetMute(bool is_target_mute); + Result IsTargetConnected(Out out_is_target_connected); + Result SetDefaultTarget(u32 target); + Result GetDefaultTarget(Out out_target); Result GetAudioOutputMode(Out out_output_mode, Set::AudioOutputModeTarget target); Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode); + Result SetForceMutePolicy(ForceMutePolicy force_mute_policy); Result GetForceMutePolicy(Out out_mute_policy); Result GetOutputModeSetting(Out out_output_mode, Set::AudioOutputModeTarget target); Result SetOutputModeSetting(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode); + Result SetOutputTarget(u32 target); + Result SetInputTargetForceEnabled(bool is_force_enabled); Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode); Result GetHeadphoneOutputLevelMode(Out out_output_level_mode); + Result AcquireAudioVolumeUpdateEventForPlayReport(OutCopyHandle out_event); + Result AcquireAudioOutputDeviceUpdateEventForPlayReport(OutCopyHandle out_event); + Result GetAudioOutputTargetForPlayReport(Out out_target); Result NotifyHeadphoneVolumeWarningDisplayedEvent(); + Result SetSystemOutputMasterVolume(f32 volume); + Result GetSystemOutputMasterVolume(Out out_volume); + Result GetAudioVolumeDataForPlayReport(Out out_volume_data); + Result UpdateHeadphoneSettings(); + Result SetVolumeMappingTableForDev(InLargeData volume_mapping_table); + Result GetAudioOutputChannelCountForPlayReport(Out out_channel_count); + Result BindAudioOutputChannelCountUpdateEventForPlayReport(OutCopyHandle out_event); Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled); Result IsSpeakerAutoMuteEnabled(Out out_is_speaker_auto_mute_enabled); + Result GetActiveOutputTarget(Out out_target); + Result GetTargetDeviceInfo(Out out_device_info, u32 target); Result AcquireTargetNotification(OutCopyHandle out_notification_event); + Result SetHearingProtectionSafeguardTimerRemainingTimeForDebug(u64 remaining_time); + Result GetHearingProtectionSafeguardTimerRemainingTimeForDebug(Out out_remaining_time); + Result SetHearingProtectionSafeguardEnabled(bool is_enabled); + Result IsHearingProtectionSafeguardEnabled(Out out_is_enabled); + Result IsHearingProtectionSafeguardMonitoringOutputForDebug(Out out_is_monitoring); + Result GetSystemInformationForDebug(OutLargeData out_info); + Result SetVolumeButtonLongPressTime(u64 long_press_time); + Result SetNativeVolumeForDebug(f32 native_volume); + Result NotifyAudioOutputTargetForPlayReport(u32 target); + Result NotifyAudioOutputChannelCountForPlayReport(u32 channel_count); + Result NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport(); + Result BindAudioVolumeUpdateEventForPlayReport(OutCopyHandle out_event); + Result BindAudioOutputTargetUpdateEventForPlayReport(OutCopyHandle out_event); + Result GetDefaultAudioOutputTargetForPlayReport(Out out_target); + Result SetAnalogInputBoostGainForPrototyping(f32 gain); KernelHelpers::ServiceContext service_context; diff --git a/src/core/hle/service/audio/audio_debug.cpp b/src/core/hle/service/audio/audio_debug.cpp new file mode 100644 index 000000000..65efe0b2b --- /dev/null +++ b/src/core/hle/service/audio/audio_debug.cpp @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/audio/audio_debug.h" + +namespace Service::Audio { + +IAudioDebugManager::IAudioDebugManager(Core::System& system_) + : ServiceFramework{system_, "auddebug"} { + // TODO: Implement debug functions +} + +IAudioDebugManager::~IAudioDebugManager() = default; + +} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_debug.h b/src/core/hle/service/audio/audio_debug.h new file mode 100644 index 000000000..870d40f9b --- /dev/null +++ b/src/core/hle/service/audio/audio_debug.h @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::Audio { + +class IAudioDebugManager final : public ServiceFramework { +public: + explicit IAudioDebugManager(Core::System& system_); + ~IAudioDebugManager() override; + +private: + // TODO: Implement debug functions +}; + +} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_device.cpp b/src/core/hle/service/audio/audio_device.cpp index 438f3cccd..735075d19 100644 --- a/src/core/hle/service/audio/audio_device.cpp +++ b/src/core/hle/service/audio/audio_device.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "audio_core/audio_core.h" @@ -22,12 +23,13 @@ IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u {4, D<&IAudioDevice::QueryAudioDeviceSystemEvent>, "QueryAudioDeviceSystemEvent"}, {5, D<&IAudioDevice::GetActiveChannelCount>, "GetActiveChannelCount"}, {6, D<&IAudioDevice::ListAudioDeviceNameAuto>, "ListAudioDeviceNameAuto"}, - {7, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"}, - {8, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"}, + {7, D<&IAudioDevice::GetAudioSystemMasterVolumeSetting>, "GetAudioSystemMasterVolumeSetting"}, + {8, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"}, + {9, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"}, {10, D<&IAudioDevice::GetActiveAudioDeviceNameAuto>, "GetActiveAudioDeviceNameAuto"}, {11, D<&IAudioDevice::QueryAudioDeviceInputEvent>, "QueryAudioDeviceInputEvent"}, {12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"}, - {13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"}, + {13, D<&IAudioDevice::GetActiveAudioOutputDeviceName>, "GetActiveAudioOutputDeviceName"}, {14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"}, }; RegisterHandlers(functions); @@ -141,6 +143,17 @@ Result IAudioDevice::GetActiveChannelCount(Out out_active_channel_count) { R_SUCCEED(); } +Result IAudioDevice::GetAudioSystemMasterVolumeSetting(Out out_volume) { + LOG_DEBUG(Service_Audio, "(STUBBED) called"); + *out_volume = 1.0f; + R_SUCCEED(); +} + +Result IAudioDevice::GetActiveAudioOutputDeviceName( + OutArray out_name) { + R_RETURN(this->GetActiveAudioDeviceNameAuto(out_name)); +} + Result IAudioDevice::ListAudioOutputDeviceName( OutArray out_names, Out out_count) { *out_count = impl->ListAudioOutputDeviceName(out_names); diff --git a/src/core/hle/service/audio/audio_device.h b/src/core/hle/service/audio/audio_device.h index 752157272..8fd4f1269 100644 --- a/src/core/hle/service/audio/audio_device.h +++ b/src/core/hle/service/audio/audio_device.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -46,6 +47,9 @@ private: Result QueryAudioDeviceInputEvent(OutCopyHandle out_event); Result QueryAudioDeviceOutputEvent(OutCopyHandle out_event); Result GetActiveChannelCount(Out out_active_channel_count); + Result GetAudioSystemMasterVolumeSetting(Out out_volume); + Result GetActiveAudioOutputDeviceName( + OutArray out_name); Result ListAudioOutputDeviceName( OutArray out_names, Out out_count); diff --git a/src/core/hle/service/audio/audio_device_service.cpp b/src/core/hle/service/audio/audio_device_service.cpp new file mode 100644 index 000000000..0af5d67fb --- /dev/null +++ b/src/core/hle/service/audio/audio_device_service.cpp @@ -0,0 +1,34 @@ +// 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_device_service.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::Audio { + +IAudioDeviceService::IAudioDeviceService(Core::System& system_, const char* name) + : ServiceFramework{system_, name} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IAudioDeviceService::RequestSuspend>, "RequestSuspend"}, + {1, D<&IAudioDeviceService::RequestResume>, "RequestResume"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAudioDeviceService::~IAudioDeviceService() = default; + +Result IAudioDeviceService::RequestSuspend(u64 process_id) { + LOG_WARNING(Service_Audio, "(STUBBED) called, process_id={:#x}", process_id); + R_SUCCEED(); +} + +Result IAudioDeviceService::RequestResume(u64 process_id) { + LOG_WARNING(Service_Audio, "(STUBBED) called, process_id={:#x}", process_id); + R_SUCCEED(); +} + +} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_device_service.h b/src/core/hle/service/audio/audio_device_service.h new file mode 100644 index 000000000..a85efd273 --- /dev/null +++ b/src/core/hle/service/audio/audio_device_service.h @@ -0,0 +1,21 @@ +// 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 Service::Audio { + +class IAudioDeviceService final : public ServiceFramework { +public: + explicit IAudioDeviceService(Core::System& system_, const char* name); + ~IAudioDeviceService() override; + +private: + Result RequestSuspend(u64 process_id); + Result RequestResume(u64 process_id); +}; + +} // namespace Service::Audio diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp new file mode 100644 index 000000000..c873f192a --- /dev/null +++ b/src/core/hle/service/audio/codecctl.cpp @@ -0,0 +1,110 @@ +// 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/codecctl.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::Audio { + +ICodecController::ICodecController(Core::System& system_) + : ServiceFramework{system_, "codecctl"}, service_context{system_, "codecctl"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ICodecController::Initialize>, "Initialize"}, + {1, D<&ICodecController::Finalize>, "Finalize"}, + {2, D<&ICodecController::Sleep>, "Sleep"}, + {3, D<&ICodecController::Wake>, "Wake"}, + {4, D<&ICodecController::SetVolume>, "SetVolume"}, + {5, D<&ICodecController::GetVolumeMax>, "GetVolumeMax"}, + {6, D<&ICodecController::GetVolumeMin>, "GetVolumeMin"}, + {7, D<&ICodecController::SetActiveTarget>, "SetActiveTarget"}, + {8, D<&ICodecController::GetActiveTarget>, "GetActiveTarget"}, + {9, D<&ICodecController::BindHeadphoneMicJackInterrupt>, "BindHeadphoneMicJackInterrupt"}, + {10, D<&ICodecController::IsHeadphoneMicJackInserted>, "IsHeadphoneMicJackInserted"}, + {11, D<&ICodecController::ClearHeadphoneMicJackInterrupt>, "ClearHeadphoneMicJackInterrupt"}, + {12, D<&ICodecController::IsRequested>, "IsRequested"}, + }; + // clang-format on + + RegisterHandlers(functions); + + mic_jack_event = service_context.CreateEvent("CodecCtl:MicJackEvent"); +} + +ICodecController::~ICodecController() { + service_context.CloseEvent(mic_jack_event); +} + +Result ICodecController::Initialize() { + LOG_INFO(Service_Audio, "called"); + R_SUCCEED(); +} + +Result ICodecController::Finalize() { + LOG_INFO(Service_Audio, "called"); + R_SUCCEED(); +} + +Result ICodecController::Sleep() { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ICodecController::Wake() { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ICodecController::SetVolume(f32 volume) { + LOG_INFO(Service_Audio, "called, volume={}", volume); + R_SUCCEED(); +} + +Result ICodecController::GetVolumeMax(Out out_volume_max) { + LOG_INFO(Service_Audio, "called"); + *out_volume_max = 1.0f; + R_SUCCEED(); +} + +Result ICodecController::GetVolumeMin(Out out_volume_min) { + LOG_INFO(Service_Audio, "called"); + *out_volume_min = 0.0f; + R_SUCCEED(); +} + +Result ICodecController::SetActiveTarget(u32 target) { + LOG_INFO(Service_Audio, "called, target={}", target); + R_SUCCEED(); +} + +Result ICodecController::GetActiveTarget(Out out_target) { + LOG_INFO(Service_Audio, "called"); + *out_target = 0; + R_SUCCEED(); +} + +Result ICodecController::BindHeadphoneMicJackInterrupt(OutCopyHandle out_event) { + LOG_INFO(Service_Audio, "called"); + *out_event = &mic_jack_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result ICodecController::IsHeadphoneMicJackInserted(Out out_is_inserted) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + *out_is_inserted = false; + R_SUCCEED(); +} + +Result ICodecController::ClearHeadphoneMicJackInterrupt() { + LOG_INFO(Service_Audio, "called"); + R_SUCCEED(); +} + +Result ICodecController::IsRequested(Out out_is_requested) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + *out_is_requested = false; + R_SUCCEED(); +} + +} // namespace Service::Audio diff --git a/src/core/hle/service/audio/codecctl.h b/src/core/hle/service/audio/codecctl.h new file mode 100644 index 000000000..ddd7028f0 --- /dev/null +++ b/src/core/hle/service/audio/codecctl.h @@ -0,0 +1,40 @@ +// 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/kernel_helpers.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::Audio { + +class ICodecController final : public ServiceFramework { +public: + explicit ICodecController(Core::System& system_); + ~ICodecController() override; + +private: + Result Initialize(); + Result Finalize(); + Result Sleep(); + Result Wake(); + Result SetVolume(f32 volume); + Result GetVolumeMax(Out out_volume_max); + Result GetVolumeMin(Out out_volume_min); + Result SetActiveTarget(u32 target); + Result GetActiveTarget(Out out_target); + Result BindHeadphoneMicJackInterrupt(OutCopyHandle out_event); + Result IsHeadphoneMicJackInserted(Out out_is_inserted); + Result ClearHeadphoneMicJackInterrupt(); + Result IsRequested(Out out_is_requested); + + KernelHelpers::ServiceContext service_context; + Kernel::KEvent* mic_jack_event; +}; + +} // namespace Service::Audio