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 <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-05-24 16:39:15 +10:00
parent 4dde579132
commit 238e8282b2
12 changed files with 582 additions and 52 deletions

View File

@@ -515,8 +515,12 @@ add_library(core STATIC
hle/service/apm/apm_interface.h hle/service/apm/apm_interface.h
hle/service/audio/audio_controller.cpp hle/service/audio/audio_controller.cpp
hle/service/audio/audio_controller.h 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.cpp
hle/service/audio/audio_device.h 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.cpp
hle/service/audio/audio_in_manager.h hle/service/audio/audio_in_manager.h
hle/service/audio/audio_in.cpp hle/service/audio/audio_in.cpp
@@ -531,6 +535,8 @@ add_library(core STATIC
hle/service/audio/audio_renderer.h hle/service/audio/audio_renderer.h
hle/service/audio/audio.cpp hle/service/audio/audio.cpp
hle/service/audio/audio.h hle/service/audio/audio.h
hle/service/audio/codecctl.cpp
hle/service/audio/codecctl.h
hle/service/audio/errors.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.cpp
hle/service/audio/final_output_recorder_manager_for_applet.h hle/service/audio/final_output_recorder_manager_for_applet.h

View File

@@ -1,12 +1,16 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/audio/audio.h" #include "core/hle/service/audio/audio.h"
#include "core/hle/service/audio/audio_controller.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_in_manager.h"
#include "core/hle/service/audio/audio_out_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_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.h"
#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h" #include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
#include "core/hle/service/audio/hardware_opus_decoder_manager.h" #include "core/hle/service/audio/hardware_opus_decoder_manager.h"
@@ -18,17 +22,38 @@ namespace Service::Audio {
void LoopProcess(Core::System& system) { void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system); auto server_manager = std::make_unique<ServerManager>(system);
// Main audio services
server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system)); server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system)); server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system));
server_manager->RegisterNamedService("audout:u", std::make_shared<IAudioOutManager>(system)); server_manager->RegisterNamedService("audout:u", std::make_shared<IAudioOutManager>(system));
server_manager->RegisterNamedService( server_manager->RegisterNamedService("audren:u", std::make_shared<IAudioRendererManager>(system));
"audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system)); server_manager->RegisterNamedService("hwopus", std::make_shared<IHardwareOpusDecoderManager>(system));
server_manager->RegisterNamedService("audrec:u",
std::make_shared<IFinalOutputRecorderManager>(system)); // Final output recorder services
server_manager->RegisterNamedService("audren:u", server_manager->RegisterNamedService("audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
std::make_shared<IAudioRendererManager>(system)); server_manager->RegisterNamedService("audrec:u", std::make_shared<IFinalOutputRecorderManager>(system));
server_manager->RegisterNamedService("hwopus",
std::make_shared<IHardwareOpusDecoderManager>(system)); // Applet versions of audio services
server_manager->RegisterNamedService("audout:a", std::make_shared<IAudioOutManager>(system));
server_manager->RegisterNamedService("audin:a", std::make_shared<IAudioInManager>(system));
server_manager->RegisterNamedService("audren:a", std::make_shared<IAudioRendererManager>(system));
// Device suspend/resume services
server_manager->RegisterNamedService("audout:d", std::make_shared<IAudioDeviceService>(system, "audout:d"));
server_manager->RegisterNamedService("audin:d", std::make_shared<IAudioDeviceService>(system, "audin:d"));
server_manager->RegisterNamedService("audrec:d", std::make_shared<IAudioDeviceService>(system, "audrec:d"));
server_manager->RegisterNamedService("audren:d", std::make_shared<IAudioDeviceService>(system, "audren:d"));
// Codec controller service
server_manager->RegisterNamedService("codecctl", std::make_shared<ICodecController>(system));
// Debug service
server_manager->RegisterNamedService("auddebug", std::make_shared<IAudioDebugManager>(system));
// System-level audio services
server_manager->RegisterNamedService("aud:a", std::make_shared<IAudioController>(system)); // System version of audctl
server_manager->RegisterNamedService("aud:d", std::make_shared<IAudioDeviceService>(system, "aud:d")); // System device service
ServerManager::RunServer(std::move(server_manager)); ServerManager::RunServer(std::move(server_manager));
} }

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h" #include "common/logging/log.h"
@@ -14,60 +15,60 @@ IAudioController::IAudioController(Core::System& system_)
: ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} { : ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, nullptr, "GetTargetVolume"}, {0, D<&IAudioController::GetTargetVolume>, "GetTargetVolume"},
{1, nullptr, "SetTargetVolume"}, {1, D<&IAudioController::SetTargetVolume>, "SetTargetVolume"},
{2, D<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"}, {2, D<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
{3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"}, {3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
{4, nullptr, "IsTargetMute"}, {4, D<&IAudioController::IsTargetMute>, "IsTargetMute"},
{5, nullptr, "SetTargetMute"}, {5, D<&IAudioController::SetTargetMute>, "SetTargetMute"},
{6, nullptr, "IsTargetConnected"}, {6, D<&IAudioController::IsTargetConnected>, "IsTargetConnected"},
{7, nullptr, "SetDefaultTarget"}, {7, D<&IAudioController::SetDefaultTarget>, "SetDefaultTarget"},
{8, nullptr, "GetDefaultTarget"}, {8, D<&IAudioController::GetDefaultTarget>, "GetDefaultTarget"},
{9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"}, {9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
{10, D<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"}, {10, D<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
{11, nullptr, "SetForceMutePolicy"}, {11, D<&IAudioController::SetForceMutePolicy>, "SetForceMutePolicy"},
{12, D<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"}, {12, D<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
{13, D<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"}, {13, D<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
{14, D<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"}, {14, D<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
{15, nullptr, "SetOutputTarget"}, {15, D<&IAudioController::SetOutputTarget>, "SetOutputTarget"},
{16, nullptr, "SetInputTargetForceEnabled"}, {16, D<&IAudioController::SetInputTargetForceEnabled>, "SetInputTargetForceEnabled"},
{17, D<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"}, {17, D<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
{18, D<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"}, {18, D<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, {19, D<&IAudioController::AcquireAudioVolumeUpdateEventForPlayReport>, "AcquireAudioVolumeUpdateEventForPlayReport"},
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, {20, D<&IAudioController::AcquireAudioOutputDeviceUpdateEventForPlayReport>, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
{21, nullptr, "GetAudioOutputTargetForPlayReport"}, {21, D<&IAudioController::GetAudioOutputTargetForPlayReport>, "GetAudioOutputTargetForPlayReport"},
{22, D<&IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent>, "NotifyHeadphoneVolumeWarningDisplayedEvent"}, {22, D<&IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent>, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
{23, nullptr, "SetSystemOutputMasterVolume"}, {23, D<&IAudioController::SetSystemOutputMasterVolume>, "SetSystemOutputMasterVolume"},
{24, nullptr, "GetSystemOutputMasterVolume"}, {24, D<&IAudioController::GetSystemOutputMasterVolume>, "GetSystemOutputMasterVolume"},
{25, nullptr, "GetAudioVolumeDataForPlayReport"}, {25, D<&IAudioController::GetAudioVolumeDataForPlayReport>, "GetAudioVolumeDataForPlayReport"},
{26, nullptr, "UpdateHeadphoneSettings"}, {26, D<&IAudioController::UpdateHeadphoneSettings>, "UpdateHeadphoneSettings"},
{27, nullptr, "SetVolumeMappingTableForDev"}, {27, D<&IAudioController::SetVolumeMappingTableForDev>, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, {28, D<&IAudioController::GetAudioOutputChannelCountForPlayReport>, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {29, D<&IAudioController::BindAudioOutputChannelCountUpdateEventForPlayReport>, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{30, D<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"}, {30, D<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
{31, D<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"}, {31, D<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"}, {32, D<&IAudioController::GetActiveOutputTarget>, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"}, {33, D<&IAudioController::GetTargetDeviceInfo>, "GetTargetDeviceInfo"},
{34, D<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"}, {34, D<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
{35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, {35, D<&IAudioController::SetHearingProtectionSafeguardTimerRemainingTimeForDebug>, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, {36, D<&IAudioController::GetHearingProtectionSafeguardTimerRemainingTimeForDebug>, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{37, nullptr, "SetHearingProtectionSafeguardEnabled"}, {37, D<&IAudioController::SetHearingProtectionSafeguardEnabled>, "SetHearingProtectionSafeguardEnabled"},
{38, nullptr, "IsHearingProtectionSafeguardEnabled"}, {38, D<&IAudioController::IsHearingProtectionSafeguardEnabled>, "IsHearingProtectionSafeguardEnabled"},
{39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"}, {39, D<&IAudioController::IsHearingProtectionSafeguardMonitoringOutputForDebug>, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
{40, nullptr, "GetSystemInformationForDebug"}, {40, D<&IAudioController::GetSystemInformationForDebug>, "GetSystemInformationForDebug"},
{41, nullptr, "SetVolumeButtonLongPressTime"}, {41, D<&IAudioController::SetVolumeButtonLongPressTime>, "SetVolumeButtonLongPressTime"},
{42, nullptr, "SetNativeVolumeForDebug"}, {42, D<&IAudioController::SetNativeVolumeForDebug>, "SetNativeVolumeForDebug"},
{10000, nullptr, "NotifyAudioOutputTargetForPlayReport"}, {10000, D<&IAudioController::NotifyAudioOutputTargetForPlayReport>, "NotifyAudioOutputTargetForPlayReport"},
{10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"}, {10001, D<&IAudioController::NotifyAudioOutputChannelCountForPlayReport>, "NotifyAudioOutputChannelCountForPlayReport"},
{10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, {10002, D<&IAudioController::NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport>, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
{10100, nullptr, "GetAudioVolumeDataForPlayReport"}, {10100, D<&IAudioController::GetAudioVolumeDataForPlayReport>, "GetAudioVolumeDataForPlayReport"},
{10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"}, {10101, D<&IAudioController::BindAudioVolumeUpdateEventForPlayReport>, "BindAudioVolumeUpdateEventForPlayReport"},
{10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"}, {10102, D<&IAudioController::BindAudioOutputTargetUpdateEventForPlayReport>, "BindAudioOutputTargetUpdateEventForPlayReport"},
{10103, nullptr, "GetAudioOutputTargetForPlayReport"}, {10103, D<&IAudioController::GetAudioOutputTargetForPlayReport>, "GetAudioOutputTargetForPlayReport"},
{10104, nullptr, "GetAudioOutputChannelCountForPlayReport"}, {10104, D<&IAudioController::GetAudioOutputChannelCountForPlayReport>, "GetAudioOutputChannelCountForPlayReport"},
{10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {10105, D<&IAudioController::BindAudioOutputChannelCountUpdateEventForPlayReport>, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, {10106, D<&IAudioController::GetDefaultAudioOutputTargetForPlayReport>, "GetDefaultAudioOutputTargetForPlayReport"},
{50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, {50000, D<&IAudioController::SetAnalogInputBoostGainForPrototyping>, "SetAnalogInputBoostGainForPrototyping"},
}; };
// clang-format on // clang-format on
@@ -176,4 +177,208 @@ Result IAudioController::AcquireTargetNotification(
R_SUCCEED(); R_SUCCEED();
} }
Result IAudioController::GetTargetVolume(Out<s32> 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<bool> 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<bool> 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<u32> 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<u32>(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<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_event = &notification_event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioController::AcquireAudioOutputDeviceUpdateEventForPlayReport(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_event = &notification_event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioController::GetAudioOutputTargetForPlayReport(Out<u32> 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<f32> out_volume) {
LOG_INFO(Audio, "called");
*out_volume = 1.0f;
R_SUCCEED();
}
Result IAudioController::GetAudioVolumeDataForPlayReport(Out<u32> 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<u32, BufferAttr_HipcMapAlias> volume_mapping_table) {
LOG_WARNING(Audio, "(STUBBED) called");
R_SUCCEED();
}
Result IAudioController::GetAudioOutputChannelCountForPlayReport(Out<u32> out_channel_count) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_channel_count = 2;
R_SUCCEED();
}
Result IAudioController::BindAudioOutputChannelCountUpdateEventForPlayReport(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_event = &notification_event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioController::GetActiveOutputTarget(Out<u32> out_target) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_target = 0;
R_SUCCEED();
}
Result IAudioController::GetTargetDeviceInfo(Out<u32> 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<u64> 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<bool> out_is_enabled) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_is_enabled = false;
R_SUCCEED();
}
Result IAudioController::IsHearingProtectionSafeguardMonitoringOutputForDebug(Out<bool> out_is_monitoring) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_is_monitoring = false;
R_SUCCEED();
}
Result IAudioController::GetSystemInformationForDebug(OutLargeData<u8, BufferAttr_HipcMapAlias> 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<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_event = &notification_event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioController::BindAudioOutputTargetUpdateEventForPlayReport(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Audio, "(STUBBED) called");
*out_event = &notification_event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioController::GetDefaultAudioOutputTargetForPlayReport(Out<u32> 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 } // namespace Service::Audio

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@@ -33,22 +34,59 @@ private:
HighPower, HighPower,
}; };
Result GetTargetVolume(Out<s32> out_target_volume);
Result SetTargetVolume(s32 target_volume);
Result GetTargetVolumeMin(Out<s32> out_target_min_volume); Result GetTargetVolumeMin(Out<s32> out_target_min_volume);
Result GetTargetVolumeMax(Out<s32> out_target_max_volume); Result GetTargetVolumeMax(Out<s32> out_target_max_volume);
Result IsTargetMute(Out<bool> out_is_target_mute);
Result SetTargetMute(bool is_target_mute);
Result IsTargetConnected(Out<bool> out_is_target_connected);
Result SetDefaultTarget(u32 target);
Result GetDefaultTarget(Out<u32> out_target);
Result GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode, Result GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
Set::AudioOutputModeTarget target); Set::AudioOutputModeTarget target);
Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode); Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode);
Result SetForceMutePolicy(ForceMutePolicy force_mute_policy);
Result GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy); Result GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy);
Result GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode, Result GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
Set::AudioOutputModeTarget target); Set::AudioOutputModeTarget target);
Result SetOutputModeSetting(Set::AudioOutputModeTarget target, Result SetOutputModeSetting(Set::AudioOutputModeTarget target,
Set::AudioOutputMode output_mode); Set::AudioOutputMode output_mode);
Result SetOutputTarget(u32 target);
Result SetInputTargetForceEnabled(bool is_force_enabled);
Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode); Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode); Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
Result AcquireAudioVolumeUpdateEventForPlayReport(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result AcquireAudioOutputDeviceUpdateEventForPlayReport(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetAudioOutputTargetForPlayReport(Out<u32> out_target);
Result NotifyHeadphoneVolumeWarningDisplayedEvent(); Result NotifyHeadphoneVolumeWarningDisplayedEvent();
Result SetSystemOutputMasterVolume(f32 volume);
Result GetSystemOutputMasterVolume(Out<f32> out_volume);
Result GetAudioVolumeDataForPlayReport(Out<u32> out_volume_data);
Result UpdateHeadphoneSettings();
Result SetVolumeMappingTableForDev(InLargeData<u32, BufferAttr_HipcMapAlias> volume_mapping_table);
Result GetAudioOutputChannelCountForPlayReport(Out<u32> out_channel_count);
Result BindAudioOutputChannelCountUpdateEventForPlayReport(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled); Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled); Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
Result GetActiveOutputTarget(Out<u32> out_target);
Result GetTargetDeviceInfo(Out<u32> out_device_info, u32 target);
Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event); Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);
Result SetHearingProtectionSafeguardTimerRemainingTimeForDebug(u64 remaining_time);
Result GetHearingProtectionSafeguardTimerRemainingTimeForDebug(Out<u64> out_remaining_time);
Result SetHearingProtectionSafeguardEnabled(bool is_enabled);
Result IsHearingProtectionSafeguardEnabled(Out<bool> out_is_enabled);
Result IsHearingProtectionSafeguardMonitoringOutputForDebug(Out<bool> out_is_monitoring);
Result GetSystemInformationForDebug(OutLargeData<u8, BufferAttr_HipcMapAlias> 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<Kernel::KReadableEvent> out_event);
Result BindAudioOutputTargetUpdateEventForPlayReport(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetDefaultAudioOutputTargetForPlayReport(Out<u32> out_target);
Result SetAnalogInputBoostGainForPrototyping(f32 gain);
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;

View File

@@ -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

View File

@@ -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<IAudioDebugManager> {
public:
explicit IAudioDebugManager(Core::System& system_);
~IAudioDebugManager() override;
private:
// TODO: Implement debug functions
};
} // namespace Service::Audio

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/audio_core.h" #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"}, {4, D<&IAudioDevice::QueryAudioDeviceSystemEvent>, "QueryAudioDeviceSystemEvent"},
{5, D<&IAudioDevice::GetActiveChannelCount>, "GetActiveChannelCount"}, {5, D<&IAudioDevice::GetActiveChannelCount>, "GetActiveChannelCount"},
{6, D<&IAudioDevice::ListAudioDeviceNameAuto>, "ListAudioDeviceNameAuto"}, {6, D<&IAudioDevice::ListAudioDeviceNameAuto>, "ListAudioDeviceNameAuto"},
{7, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"}, {7, D<&IAudioDevice::GetAudioSystemMasterVolumeSetting>, "GetAudioSystemMasterVolumeSetting"},
{8, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"}, {8, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"},
{9, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"},
{10, D<&IAudioDevice::GetActiveAudioDeviceNameAuto>, "GetActiveAudioDeviceNameAuto"}, {10, D<&IAudioDevice::GetActiveAudioDeviceNameAuto>, "GetActiveAudioDeviceNameAuto"},
{11, D<&IAudioDevice::QueryAudioDeviceInputEvent>, "QueryAudioDeviceInputEvent"}, {11, D<&IAudioDevice::QueryAudioDeviceInputEvent>, "QueryAudioDeviceInputEvent"},
{12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"}, {12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"},
{13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"}, {13, D<&IAudioDevice::GetActiveAudioOutputDeviceName>, "GetActiveAudioOutputDeviceName"},
{14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"}, {14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"},
}; };
RegisterHandlers(functions); RegisterHandlers(functions);
@@ -141,6 +143,17 @@ Result IAudioDevice::GetActiveChannelCount(Out<u32> out_active_channel_count) {
R_SUCCEED(); R_SUCCEED();
} }
Result IAudioDevice::GetAudioSystemMasterVolumeSetting(Out<f32> out_volume) {
LOG_DEBUG(Service_Audio, "(STUBBED) called");
*out_volume = 1.0f;
R_SUCCEED();
}
Result IAudioDevice::GetActiveAudioOutputDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name) {
R_RETURN(this->GetActiveAudioDeviceNameAuto(out_name));
}
Result IAudioDevice::ListAudioOutputDeviceName( Result IAudioDevice::ListAudioOutputDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) { OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
*out_count = impl->ListAudioOutputDeviceName(out_names); *out_count = impl->ListAudioOutputDeviceName(out_names);

View File

@@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@@ -46,6 +47,9 @@ private:
Result QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetActiveChannelCount(Out<u32> out_active_channel_count); Result GetActiveChannelCount(Out<u32> out_active_channel_count);
Result GetAudioSystemMasterVolumeSetting(Out<f32> out_volume);
Result GetActiveAudioOutputDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name);
Result ListAudioOutputDeviceName( Result ListAudioOutputDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
Out<s32> out_count); Out<s32> out_count);

View File

@@ -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

View File

@@ -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<IAudioDeviceService> {
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

View File

@@ -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<f32> out_volume_max) {
LOG_INFO(Service_Audio, "called");
*out_volume_max = 1.0f;
R_SUCCEED();
}
Result ICodecController::GetVolumeMin(Out<f32> 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<u32> out_target) {
LOG_INFO(Service_Audio, "called");
*out_target = 0;
R_SUCCEED();
}
Result ICodecController::BindHeadphoneMicJackInterrupt(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_Audio, "called");
*out_event = &mic_jack_event->GetReadableEvent();
R_SUCCEED();
}
Result ICodecController::IsHeadphoneMicJackInserted(Out<bool> 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<bool> out_is_requested) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
*out_is_requested = false;
R_SUCCEED();
}
} // namespace Service::Audio

View File

@@ -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<ICodecController> {
public:
explicit ICodecController(Core::System& system_);
~ICodecController() override;
private:
Result Initialize();
Result Finalize();
Result Sleep();
Result Wake();
Result SetVolume(f32 volume);
Result GetVolumeMax(Out<f32> out_volume_max);
Result GetVolumeMin(Out<f32> out_volume_min);
Result SetActiveTarget(u32 target);
Result GetActiveTarget(Out<u32> out_target);
Result BindHeadphoneMicJackInterrupt(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsHeadphoneMicJackInserted(Out<bool> out_is_inserted);
Result ClearHeadphoneMicJackInterrupt();
Result IsRequested(Out<bool> out_is_requested);
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* mic_jack_event;
};
} // namespace Service::Audio