// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "audio_core/out/audio_out.h" #include "audio_core/out/audio_out_system.h" #include "core/hle/kernel/k_process.h" #include "core/hle/service/audio/audio_out.h" #include "core/hle/service/cmif_serialization.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/service.h" namespace Service::Audio { using namespace AudioCore::AudioOut; IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id, const std::string& device_name, const AudioOutParameter& in_params, Kernel::KProcess* handle, u64 applet_resource_user_id) : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, event{service_context.CreateEvent("AudioOutEvent")}, process{handle}, impl{std::make_shared(system_, manager, event, session_id)} { // clang-format off static const FunctionInfo functions[] = { {0, C<&IAudioOut::GetAudioOutState>, "GetAudioOutState"}, {1, C<&IAudioOut::Start>, "Start"}, {2, C<&IAudioOut::Stop>, "Stop"}, {3, C<&IAudioOut::AppendAudioOutBuffer>, "AppendAudioOutBuffer"}, {4, C<&IAudioOut::RegisterBufferEvent>, "RegisterBufferEvent"}, {5, C<&IAudioOut::GetReleasedAudioOutBuffers>, "GetReleasedAudioOutBuffers"}, {6, C<&IAudioOut::ContainsAudioOutBuffer>, "ContainsAudioOutBuffer"}, {7, C<&IAudioOut::AppendAudioOutBufferAuto>, "AppendAudioOutBufferAuto"}, {8, C<&IAudioOut::GetReleasedAudioOutBuffersAuto>, "GetReleasedAudioOutBuffersAuto"}, {9, C<&IAudioOut::GetAudioOutBufferCount>, "GetAudioOutBufferCount"}, {10, C<&IAudioOut::GetAudioOutPlayedSampleCount>, "GetAudioOutPlayedSampleCount"}, {11, C<&IAudioOut::FlushAudioOutBuffers>, "FlushAudioOutBuffers"}, {12, C<&IAudioOut::SetAudioOutVolume>, "SetAudioOutVolume"}, {13, C<&IAudioOut::GetAudioOutVolume>, "GetAudioOutVolume"}, }; // clang-format on RegisterHandlers(functions); process->Open(); } IAudioOut::~IAudioOut() { impl->Free(); service_context.CloseEvent(event); process->Close(); } Result IAudioOut::GetAudioOutState(Out out_state) { *out_state = static_cast(impl->GetState()); LOG_DEBUG(Service_Audio, "called. state={}", *out_state); R_SUCCEED(); } Result IAudioOut::Start() { LOG_DEBUG(Service_Audio, "called"); R_RETURN(impl->StartSystem()); } Result IAudioOut::Stop() { LOG_DEBUG(Service_Audio, "called"); R_RETURN(impl->StopSystem()); } Result IAudioOut::AppendAudioOutBuffer( InArray audio_out_buffer, u64 buffer_client_ptr) { R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr)); } Result IAudioOut::AppendAudioOutBufferAuto( InArray audio_out_buffer, u64 buffer_client_ptr) { if (audio_out_buffer.empty()) { LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!"); R_THROW(Audio::ResultInsufficientBuffer); } LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", impl->GetSystem().GetSessionId(), buffer_client_ptr); R_RETURN(impl->AppendBuffer(audio_out_buffer[0], buffer_client_ptr)); } Result IAudioOut::RegisterBufferEvent(OutCopyHandle out_event) { LOG_DEBUG(Service_Audio, "called"); *out_event = &impl->GetBufferEvent(); R_SUCCEED(); } Result IAudioOut::GetReleasedAudioOutBuffers( OutArray out_audio_buffer, Out out_count) { R_RETURN(this->GetReleasedAudioOutBuffersAuto(out_audio_buffer, out_count)); } Result IAudioOut::GetReleasedAudioOutBuffersAuto( OutArray out_audio_buffer, Out out_count) { if (!out_audio_buffer.empty()) { out_audio_buffer[0] = 0; } *out_count = impl->GetReleasedBuffers(out_audio_buffer); LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", impl->GetSystem().GetSessionId(), *out_count); R_SUCCEED(); } Result IAudioOut::ContainsAudioOutBuffer(Out out_contains_buffer, u64 buffer_client_ptr) { *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr); LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr, *out_contains_buffer); R_SUCCEED(); } Result IAudioOut::GetAudioOutBufferCount(Out out_buffer_count) { *out_buffer_count = impl->GetBufferCount(); LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count); R_SUCCEED(); } Result IAudioOut::GetAudioOutPlayedSampleCount(Out out_played_sample_count) { *out_played_sample_count = impl->GetPlayedSampleCount(); LOG_DEBUG(Service_Audio, "called. Played samples={}", *out_played_sample_count); R_SUCCEED(); } Result IAudioOut::FlushAudioOutBuffers(Out out_flushed) { *out_flushed = impl->FlushAudioOutBuffers(); LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed); R_SUCCEED(); } Result IAudioOut::SetAudioOutVolume(f32 volume) { LOG_DEBUG(Service_Audio, "called. Volume={}", volume); impl->SetVolume(volume); R_SUCCEED(); } Result IAudioOut::GetAudioOutVolume(Out out_volume) { *out_volume = impl->GetVolume(); LOG_DEBUG(Service_Audio, "called. Volume={}", *out_volume); R_SUCCEED(); } } // namespace Service::Audio