mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	audio: split IAudioDevice, IAudioRenderer, move IAudioRendererManager
This commit is contained in:
		@@ -489,6 +489,10 @@ add_library(core STATIC
 | 
				
			|||||||
    hle/service/apm/apm_controller.h
 | 
					    hle/service/apm/apm_controller.h
 | 
				
			||||||
    hle/service/apm/apm_interface.cpp
 | 
					    hle/service/apm/apm_interface.cpp
 | 
				
			||||||
    hle/service/apm/apm_interface.h
 | 
					    hle/service/apm/apm_interface.h
 | 
				
			||||||
 | 
					    hle/service/audio/audio_controller.cpp
 | 
				
			||||||
 | 
					    hle/service/audio/audio_controller.h
 | 
				
			||||||
 | 
					    hle/service/audio/audio_device.cpp
 | 
				
			||||||
 | 
					    hle/service/audio/audio_device.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
 | 
				
			||||||
@@ -497,12 +501,12 @@ add_library(core STATIC
 | 
				
			|||||||
    hle/service/audio/audio_out_manager.h
 | 
					    hle/service/audio/audio_out_manager.h
 | 
				
			||||||
    hle/service/audio/audio_out.cpp
 | 
					    hle/service/audio/audio_out.cpp
 | 
				
			||||||
    hle/service/audio/audio_out.h
 | 
					    hle/service/audio/audio_out.h
 | 
				
			||||||
 | 
					    hle/service/audio/audio_renderer_manager.cpp
 | 
				
			||||||
 | 
					    hle/service/audio/audio_renderer_manager.h
 | 
				
			||||||
 | 
					    hle/service/audio/audio_renderer.cpp
 | 
				
			||||||
 | 
					    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/audio_controller.cpp
 | 
					 | 
				
			||||||
    hle/service/audio/audio_controller.h
 | 
					 | 
				
			||||||
    hle/service/audio/audren_u.cpp
 | 
					 | 
				
			||||||
    hle/service/audio/audren_u.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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
#include "core/hle/service/audio/audio_controller.h"
 | 
					#include "core/hle/service/audio/audio_controller.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/audren_u.h"
 | 
					#include "core/hle/service/audio/audio_renderer_manager.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/hwopus.h"
 | 
					#include "core/hle/service/audio/hwopus.h"
 | 
				
			||||||
@@ -25,7 +25,8 @@ void LoopProcess(Core::System& system) {
 | 
				
			|||||||
        "audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
 | 
					        "audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
 | 
				
			||||||
    server_manager->RegisterNamedService("audrec:u",
 | 
					    server_manager->RegisterNamedService("audrec:u",
 | 
				
			||||||
                                         std::make_shared<IFinalOutputRecorderManager>(system));
 | 
					                                         std::make_shared<IFinalOutputRecorderManager>(system));
 | 
				
			||||||
    server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));
 | 
					    server_manager->RegisterNamedService("audren:u",
 | 
				
			||||||
 | 
					                                         std::make_shared<IAudioRendererManager>(system));
 | 
				
			||||||
    server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
 | 
					    server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
 | 
				
			||||||
    ServerManager::RunServer(std::move(server_manager));
 | 
					    ServerManager::RunServer(std::move(server_manager));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										183
									
								
								src/core/hle/service/audio/audio_device.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/core/hle/service/audio/audio_device.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,183 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio_core/audio_core.h"
 | 
				
			||||||
 | 
					#include "common/string_util.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/audio/audio_device.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/ipc_helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::Audio {
 | 
				
			||||||
 | 
					using namespace AudioCore::Renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
 | 
				
			||||||
 | 
					                           u32 device_num)
 | 
				
			||||||
 | 
					    : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
 | 
				
			||||||
 | 
					      impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
 | 
				
			||||||
 | 
					      event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
 | 
				
			||||||
 | 
					    static const FunctionInfo functions[] = {
 | 
				
			||||||
 | 
					        {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
 | 
				
			||||||
 | 
					        {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
 | 
				
			||||||
 | 
					        {2, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolume"},
 | 
				
			||||||
 | 
					        {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
 | 
				
			||||||
 | 
					        {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
 | 
				
			||||||
 | 
					        {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
 | 
				
			||||||
 | 
					        {6, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceNameAuto"},
 | 
				
			||||||
 | 
					        {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
 | 
				
			||||||
 | 
					        {8, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolumeAuto"},
 | 
				
			||||||
 | 
					        {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
 | 
				
			||||||
 | 
					        {11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
 | 
				
			||||||
 | 
					        {12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
 | 
				
			||||||
 | 
					        {13, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioOutputDeviceName"},
 | 
				
			||||||
 | 
					        {14, &IAudioDevice::ListAudioOutputDeviceName, "ListAudioOutputDeviceName"},
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    RegisterHandlers(functions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    event->Signal();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IAudioDevice::~IAudioDevice() {
 | 
				
			||||||
 | 
					    service_context.CloseEvent(event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::ListAudioDeviceName(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<AudioDevice::AudioDeviceName> out_names{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const u32 out_count = impl->ListAudioDeviceName(out_names, in_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string out{};
 | 
				
			||||||
 | 
					    for (u32 i = 0; i < out_count; i++) {
 | 
				
			||||||
 | 
					        std::string a{};
 | 
				
			||||||
 | 
					        u32 j = 0;
 | 
				
			||||||
 | 
					        while (out_names[i].name[j] != '\0') {
 | 
				
			||||||
 | 
					            a += out_names[i].name[j];
 | 
				
			||||||
 | 
					            j++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        out += "\n\t" + a;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.WriteBuffer(out_names);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(out_count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::SetAudioDeviceOutputVolume(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    const f32 volume = rp.Pop<f32>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto device_name_buffer = ctx.ReadBuffer();
 | 
				
			||||||
 | 
					    const std::string name = Common::StringFromBuffer(device_name_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called. name={}, volume={}", name, volume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (name == "AudioTvOutput") {
 | 
				
			||||||
 | 
					        impl->SetDeviceVolumes(volume);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::GetAudioDeviceOutputVolume(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const auto device_name_buffer = ctx.ReadBuffer();
 | 
				
			||||||
 | 
					    const std::string name = Common::StringFromBuffer(device_name_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called. Name={}", name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    f32 volume{1.0f};
 | 
				
			||||||
 | 
					    if (name == "AudioTvOutput") {
 | 
				
			||||||
 | 
					        volume = impl->GetDeviceVolume(name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(volume);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::GetActiveAudioDeviceName(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const auto write_size = ctx.GetWriteBufferSize();
 | 
				
			||||||
 | 
					    std::string out_name{"AudioTvOutput"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    out_name.resize(write_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.WriteBuffer(out_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::QueryAudioDeviceSystemEvent(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "(STUBBED) called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    event->Signal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushCopyObjects(event->GetReadableEvent());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::GetActiveChannelCount(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const auto& sink{system.AudioCore().GetOutputSink()};
 | 
				
			||||||
 | 
					    u32 channel_count{sink.GetSystemChannels()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push<u32>(channel_count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::QueryAudioDeviceInputEvent(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "(STUBBED) called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushCopyObjects(event->GetReadableEvent());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::QueryAudioDeviceOutputEvent(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushCopyObjects(event->GetReadableEvent());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioDevice::ListAudioOutputDeviceName(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<AudioDevice::AudioDeviceName> out_names{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string out{};
 | 
				
			||||||
 | 
					    for (u32 i = 0; i < out_count; i++) {
 | 
				
			||||||
 | 
					        std::string a{};
 | 
				
			||||||
 | 
					        u32 j = 0;
 | 
				
			||||||
 | 
					        while (out_names[i].name[j] != '\0') {
 | 
				
			||||||
 | 
					            a += out_names[i].name[j];
 | 
				
			||||||
 | 
					            j++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        out += "\n\t" + a;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.WriteBuffer(out_names);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(out_count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::Audio
 | 
				
			||||||
							
								
								
									
										35
									
								
								src/core/hle/service/audio/audio_device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/core/hle/service/audio/audio_device.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio_core/renderer/audio_device.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/kernel_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::Audio {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class IAudioDevice final : public ServiceFramework<IAudioDevice> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
 | 
				
			||||||
 | 
					                          u32 device_num);
 | 
				
			||||||
 | 
					    ~IAudioDevice() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    void ListAudioDeviceName(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void SetAudioDeviceOutputVolume(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetAudioDeviceOutputVolume(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetActiveAudioDeviceName(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void QueryAudioDeviceSystemEvent(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetActiveChannelCount(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void QueryAudioDeviceInputEvent(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void QueryAudioDeviceOutputEvent(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void ListAudioOutputDeviceName(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KernelHelpers::ServiceContext service_context;
 | 
				
			||||||
 | 
					    std::unique_ptr<AudioCore::Renderer::AudioDevice> impl;
 | 
				
			||||||
 | 
					    Kernel::KEvent* event;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::Audio
 | 
				
			||||||
							
								
								
									
										210
									
								
								src/core/hle/service/audio/audio_renderer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								src/core/hle/service/audio/audio_renderer.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "core/hle/service/audio/audio_renderer.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/ipc_helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::Audio {
 | 
				
			||||||
 | 
					using namespace AudioCore::Renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
 | 
				
			||||||
 | 
					                               AudioCore::AudioRendererParameterInternal& params,
 | 
				
			||||||
 | 
					                               Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
 | 
				
			||||||
 | 
					                               u32 process_handle, Kernel::KProcess& process_,
 | 
				
			||||||
 | 
					                               u64 applet_resource_user_id, s32 session_id)
 | 
				
			||||||
 | 
					    : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
 | 
				
			||||||
 | 
					      rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
 | 
				
			||||||
 | 
					      impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
 | 
				
			||||||
 | 
					    // clang-format off
 | 
				
			||||||
 | 
					    static const FunctionInfo functions[] = {
 | 
				
			||||||
 | 
					        {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
 | 
				
			||||||
 | 
					        {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
 | 
				
			||||||
 | 
					        {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
 | 
				
			||||||
 | 
					        {3, &IAudioRenderer::GetState, "GetState"},
 | 
				
			||||||
 | 
					        {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"},
 | 
				
			||||||
 | 
					        {5, &IAudioRenderer::Start, "Start"},
 | 
				
			||||||
 | 
					        {6, &IAudioRenderer::Stop, "Stop"},
 | 
				
			||||||
 | 
					        {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
 | 
				
			||||||
 | 
					        {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
 | 
				
			||||||
 | 
					        {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
 | 
				
			||||||
 | 
					        {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
 | 
				
			||||||
 | 
					        {11, nullptr, "ExecuteAudioRendererRendering"},
 | 
				
			||||||
 | 
					        {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
 | 
				
			||||||
 | 
					        {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    // clang-format on
 | 
				
			||||||
 | 
					    RegisterHandlers(functions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process.Open();
 | 
				
			||||||
 | 
					    impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
 | 
				
			||||||
 | 
					                     applet_resource_user_id, session_id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IAudioRenderer::~IAudioRenderer() {
 | 
				
			||||||
 | 
					    impl->Finalize();
 | 
				
			||||||
 | 
					    service_context.CloseEvent(rendered_event);
 | 
				
			||||||
 | 
					    process.Close();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::GetSampleRate(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const auto sample_rate{impl->GetSystem().GetSampleRate()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(sample_rate);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::GetSampleCount(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const auto sample_count{impl->GetSystem().GetSampleCount()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(sample_count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::GetState(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    const u32 state{!impl->GetSystem().IsActive()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called, state {}", state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::GetMixBufferCount(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto buffer_count{impl->GetSystem().GetMixBufferCount()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(buffer_count);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::RequestUpdate(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_TRACE(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto input{ctx.ReadBuffer(0)};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
 | 
				
			||||||
 | 
					    // checking size 0. Performance size is 0 for most games.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
 | 
				
			||||||
 | 
					    if (is_buffer_b) {
 | 
				
			||||||
 | 
					        const auto buffersB{ctx.BufferDescriptorB()};
 | 
				
			||||||
 | 
					        output_buffer.resize_destructive(buffersB[0].Size());
 | 
				
			||||||
 | 
					        performance_buffer.resize_destructive(buffersB[1].Size());
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        const auto buffersC{ctx.BufferDescriptorC()};
 | 
				
			||||||
 | 
					        output_buffer.resize_destructive(buffersC[0].Size());
 | 
				
			||||||
 | 
					        performance_buffer.resize_destructive(buffersC[1].Size());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto result = impl->RequestUpdate(input, performance_buffer, output_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result.IsSuccess()) {
 | 
				
			||||||
 | 
					        if (is_buffer_b) {
 | 
				
			||||||
 | 
					            ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0);
 | 
				
			||||||
 | 
					            ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0);
 | 
				
			||||||
 | 
					            ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::Start(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl->Start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::Stop(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    impl->Stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::QuerySystemEvent(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
 | 
				
			||||||
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					        rb.Push(Audio::ResultNotSupported);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushCopyObjects(rendered_event->GetReadableEvent());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::SetRenderingTimeLimit(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    auto limit = rp.PopRaw<u32>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto& system_ = impl->GetSystem();
 | 
				
			||||||
 | 
					    system_.SetRenderingTimeLimit(limit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::GetRenderingTimeLimit(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto& system_ = impl->GetSystem();
 | 
				
			||||||
 | 
					    auto time = system_.GetRenderingTimeLimit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(time);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::ExecuteAudioRendererRendering(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::SetVoiceDropParameter(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    auto voice_drop_param{rp.Pop<f32>()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto& system_ = impl->GetSystem();
 | 
				
			||||||
 | 
					    system_.SetVoiceDropParameter(voice_drop_param);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRenderer::GetVoiceDropParameter(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto& system_ = impl->GetSystem();
 | 
				
			||||||
 | 
					    auto voice_drop_param{system_.GetVoiceDropParameter()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 3};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.Push(voice_drop_param);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::Audio
 | 
				
			||||||
							
								
								
									
										45
									
								
								src/core/hle/service/audio/audio_renderer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/core/hle/service/audio/audio_renderer.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio_core/renderer/audio_renderer.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/kernel_helpers.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::Audio {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_,
 | 
				
			||||||
 | 
					                            AudioCore::AudioRendererParameterInternal& params,
 | 
				
			||||||
 | 
					                            Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
 | 
				
			||||||
 | 
					                            u32 process_handle, Kernel::KProcess& process_,
 | 
				
			||||||
 | 
					                            u64 applet_resource_user_id, s32 session_id);
 | 
				
			||||||
 | 
					    ~IAudioRenderer() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    void GetSampleRate(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetSampleCount(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetState(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetMixBufferCount(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void RequestUpdate(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void Start(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void Stop(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void QuerySystemEvent(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void SetRenderingTimeLimit(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetRenderingTimeLimit(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void ExecuteAudioRendererRendering(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void SetVoiceDropParameter(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					    void GetVoiceDropParameter(HLERequestContext& ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KernelHelpers::ServiceContext service_context;
 | 
				
			||||||
 | 
					    Kernel::KEvent* rendered_event;
 | 
				
			||||||
 | 
					    AudioCore::Renderer::Manager& manager;
 | 
				
			||||||
 | 
					    std::unique_ptr<AudioCore::Renderer::Renderer> impl;
 | 
				
			||||||
 | 
					    Kernel::KProcess& process;
 | 
				
			||||||
 | 
					    Common::ScratchBuffer<u8> output_buffer;
 | 
				
			||||||
 | 
					    Common::ScratchBuffer<u8> performance_buffer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::Audio
 | 
				
			||||||
							
								
								
									
										143
									
								
								src/core/hle/service/audio/audio_renderer_manager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/core/hle/service/audio/audio_renderer_manager.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio_core/audio_render_manager.h"
 | 
				
			||||||
 | 
					#include "audio_core/common/feature_support.h"
 | 
				
			||||||
 | 
					#include "core/hle/kernel/k_process.h"
 | 
				
			||||||
 | 
					#include "core/hle/kernel/k_transfer_memory.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/audio/audio_device.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/audio/audio_renderer.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/audio/audio_renderer_manager.h"
 | 
				
			||||||
 | 
					#include "core/hle/service/ipc_helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Service::Audio {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace AudioCore::Renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IAudioRendererManager::IAudioRendererManager(Core::System& system_)
 | 
				
			||||||
 | 
					    : ServiceFramework{system_, "audren:u"}, service_context{system_, "audren:u"},
 | 
				
			||||||
 | 
					      impl{std::make_unique<Manager>(system_)} {
 | 
				
			||||||
 | 
					    // clang-format off
 | 
				
			||||||
 | 
					    static const FunctionInfo functions[] = {
 | 
				
			||||||
 | 
					        {0, &IAudioRendererManager::OpenAudioRenderer, "OpenAudioRenderer"},
 | 
				
			||||||
 | 
					        {1, &IAudioRendererManager::GetWorkBufferSize, "GetWorkBufferSize"},
 | 
				
			||||||
 | 
					        {2, &IAudioRendererManager::GetAudioDeviceService, "GetAudioDeviceService"},
 | 
				
			||||||
 | 
					        {3, nullptr, "OpenAudioRendererForManualExecution"},
 | 
				
			||||||
 | 
					        {4, &IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    // clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RegisterHandlers(functions);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IAudioRendererManager::~IAudioRendererManager() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRendererManager::OpenAudioRenderer(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AudioCore::AudioRendererParameterInternal params;
 | 
				
			||||||
 | 
					    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
 | 
				
			||||||
 | 
					    rp.Skip(1, false);
 | 
				
			||||||
 | 
					    auto transfer_memory_size = rp.Pop<u64>();
 | 
				
			||||||
 | 
					    auto applet_resource_user_id = rp.Pop<u64>();
 | 
				
			||||||
 | 
					    auto transfer_memory_handle = ctx.GetCopyHandle(0);
 | 
				
			||||||
 | 
					    auto process_handle = ctx.GetCopyHandle(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
 | 
				
			||||||
 | 
					        LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
 | 
				
			||||||
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					        rb.Push(Audio::ResultOutOfSessions);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
 | 
				
			||||||
 | 
					    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto session_id{impl->GetSessionId()};
 | 
				
			||||||
 | 
					    if (session_id == -1) {
 | 
				
			||||||
 | 
					        LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
 | 
				
			||||||
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
 | 
					        rb.Push(Audio::ResultOutOfSessions);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
 | 
				
			||||||
 | 
					              impl->GetSessionCount());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
 | 
				
			||||||
 | 
					                                        transfer_memory_size, process_handle, *process,
 | 
				
			||||||
 | 
					                                        applet_resource_user_id, session_id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRendererManager::GetWorkBufferSize(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    AudioCore::AudioRendererParameterInternal params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u64 size{0};
 | 
				
			||||||
 | 
					    auto result = impl->GetWorkBufferSize(params, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string output_info{};
 | 
				
			||||||
 | 
					    output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
 | 
				
			||||||
 | 
					    output_info +=
 | 
				
			||||||
 | 
					        fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
 | 
				
			||||||
 | 
					    output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
 | 
				
			||||||
 | 
					                               static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
 | 
				
			||||||
 | 
					    output_info += fmt::format(
 | 
				
			||||||
 | 
					        "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
 | 
				
			||||||
 | 
					        "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
 | 
				
			||||||
 | 
					        "Context {:04X}",
 | 
				
			||||||
 | 
					        params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
 | 
				
			||||||
 | 
					        params.splitter_destinations, params.voices, params.perf_frames,
 | 
				
			||||||
 | 
					        params.external_context_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
 | 
				
			||||||
 | 
					              output_info, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 4};
 | 
				
			||||||
 | 
					    rb.Push(result);
 | 
				
			||||||
 | 
					    rb.Push<u64>(size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRendererManager::GetAudioDeviceService(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto applet_resource_user_id = rp.Pop<u64>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called. Applet resource id {}", applet_resource_user_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id,
 | 
				
			||||||
 | 
					                                      ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRendererManager::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    LOG_ERROR(Service_Audio, "called. Implement me!");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
 | 
				
			||||||
 | 
					    struct Parameters {
 | 
				
			||||||
 | 
					        u32 revision;
 | 
				
			||||||
 | 
					        u64 applet_resource_user_id;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::RequestParser rp{ctx};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto [revision, applet_resource_user_id] = rp.PopRaw<Parameters>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOG_DEBUG(Service_Audio, "called. Revision {} Applet resource id {}",
 | 
				
			||||||
 | 
					              AudioCore::GetRevisionNum(revision), applet_resource_user_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb.Push(ResultSuccess);
 | 
				
			||||||
 | 
					    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id, revision,
 | 
				
			||||||
 | 
					                                      num_audio_devices++);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Service::Audio
 | 
				
			||||||
@@ -4,7 +4,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "audio_core/audio_render_manager.h"
 | 
					#include "audio_core/audio_render_manager.h"
 | 
				
			||||||
#include "common/scratch_buffer.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/kernel_helpers.h"
 | 
					#include "core/hle/service/kernel_helpers.h"
 | 
				
			||||||
#include "core/hle/service/service.h"
 | 
					#include "core/hle/service/service.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,10 +14,10 @@ class System;
 | 
				
			|||||||
namespace Service::Audio {
 | 
					namespace Service::Audio {
 | 
				
			||||||
class IAudioRenderer;
 | 
					class IAudioRenderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AudRenU final : public ServiceFramework<AudRenU> {
 | 
					class IAudioRendererManager final : public ServiceFramework<IAudioRendererManager> {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit AudRenU(Core::System& system_);
 | 
					    explicit IAudioRendererManager(Core::System& system_);
 | 
				
			||||||
    ~AudRenU() override;
 | 
					    ~IAudioRendererManager() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    void OpenAudioRenderer(HLERequestContext& ctx);
 | 
					    void OpenAudioRenderer(HLERequestContext& ctx);
 | 
				
			||||||
@@ -1,552 +0,0 @@
 | 
				
			|||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
					 | 
				
			||||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <array>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "audio_core/audio_core.h"
 | 
					 | 
				
			||||||
#include "audio_core/common/audio_renderer_parameter.h"
 | 
					 | 
				
			||||||
#include "audio_core/common/feature_support.h"
 | 
					 | 
				
			||||||
#include "audio_core/renderer/audio_device.h"
 | 
					 | 
				
			||||||
#include "audio_core/renderer/audio_renderer.h"
 | 
					 | 
				
			||||||
#include "audio_core/renderer/voice/voice_info.h"
 | 
					 | 
				
			||||||
#include "common/alignment.h"
 | 
					 | 
				
			||||||
#include "common/bit_util.h"
 | 
					 | 
				
			||||||
#include "common/common_funcs.h"
 | 
					 | 
				
			||||||
#include "common/logging/log.h"
 | 
					 | 
				
			||||||
#include "common/polyfill_ranges.h"
 | 
					 | 
				
			||||||
#include "common/scratch_buffer.h"
 | 
					 | 
				
			||||||
#include "common/string_util.h"
 | 
					 | 
				
			||||||
#include "core/core.h"
 | 
					 | 
				
			||||||
#include "core/hle/kernel/k_event.h"
 | 
					 | 
				
			||||||
#include "core/hle/kernel/k_process.h"
 | 
					 | 
				
			||||||
#include "core/hle/kernel/k_transfer_memory.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/audio/audren_u.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/audio/errors.h"
 | 
					 | 
				
			||||||
#include "core/hle/service/ipc_helpers.h"
 | 
					 | 
				
			||||||
#include "core/memory.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using namespace AudioCore::Renderer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Service::Audio {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    explicit IAudioRenderer(Core::System& system_, Manager& manager_,
 | 
					 | 
				
			||||||
                            AudioCore::AudioRendererParameterInternal& params,
 | 
					 | 
				
			||||||
                            Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
 | 
					 | 
				
			||||||
                            u32 process_handle, Kernel::KProcess& process_,
 | 
					 | 
				
			||||||
                            u64 applet_resource_user_id, s32 session_id)
 | 
					 | 
				
			||||||
        : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
 | 
					 | 
				
			||||||
          rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
 | 
					 | 
				
			||||||
          impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
 | 
					 | 
				
			||||||
        // clang-format off
 | 
					 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					 | 
				
			||||||
            {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
 | 
					 | 
				
			||||||
            {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
 | 
					 | 
				
			||||||
            {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
 | 
					 | 
				
			||||||
            {3, &IAudioRenderer::GetState, "GetState"},
 | 
					 | 
				
			||||||
            {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"},
 | 
					 | 
				
			||||||
            {5, &IAudioRenderer::Start, "Start"},
 | 
					 | 
				
			||||||
            {6, &IAudioRenderer::Stop, "Stop"},
 | 
					 | 
				
			||||||
            {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
 | 
					 | 
				
			||||||
            {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
 | 
					 | 
				
			||||||
            {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
 | 
					 | 
				
			||||||
            {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
 | 
					 | 
				
			||||||
            {11, nullptr, "ExecuteAudioRendererRendering"},
 | 
					 | 
				
			||||||
            {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
 | 
					 | 
				
			||||||
            {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        // clang-format on
 | 
					 | 
				
			||||||
        RegisterHandlers(functions);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        process.Open();
 | 
					 | 
				
			||||||
        impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
 | 
					 | 
				
			||||||
                         applet_resource_user_id, session_id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ~IAudioRenderer() override {
 | 
					 | 
				
			||||||
        impl->Finalize();
 | 
					 | 
				
			||||||
        service_context.CloseEvent(rendered_event);
 | 
					 | 
				
			||||||
        process.Close();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    void GetSampleRate(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const auto sample_rate{impl->GetSystem().GetSampleRate()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(sample_rate);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetSampleCount(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const auto sample_count{impl->GetSystem().GetSampleCount()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(sample_count);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetState(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const u32 state{!impl->GetSystem().IsActive()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called, state {}", state);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(state);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetMixBufferCount(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const auto buffer_count{impl->GetSystem().GetMixBufferCount()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(buffer_count);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void RequestUpdate(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_TRACE(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const auto input{ctx.ReadBuffer(0)};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
 | 
					 | 
				
			||||||
        // checking size 0. Performance size is 0 for most games.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
 | 
					 | 
				
			||||||
        if (is_buffer_b) {
 | 
					 | 
				
			||||||
            const auto buffersB{ctx.BufferDescriptorB()};
 | 
					 | 
				
			||||||
            output_buffer.resize_destructive(buffersB[0].Size());
 | 
					 | 
				
			||||||
            performance_buffer.resize_destructive(buffersB[1].Size());
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            const auto buffersC{ctx.BufferDescriptorC()};
 | 
					 | 
				
			||||||
            output_buffer.resize_destructive(buffersC[0].Size());
 | 
					 | 
				
			||||||
            performance_buffer.resize_destructive(buffersC[1].Size());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto result = impl->RequestUpdate(input, performance_buffer, output_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (result.IsSuccess()) {
 | 
					 | 
				
			||||||
            if (is_buffer_b) {
 | 
					 | 
				
			||||||
                ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0);
 | 
					 | 
				
			||||||
                ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0);
 | 
					 | 
				
			||||||
                ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!",
 | 
					 | 
				
			||||||
                      result.GetDescription());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(result);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void Start(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        impl->Start();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void Stop(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        impl->Stop();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void QuerySystemEvent(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
 | 
					 | 
				
			||||||
            IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
            rb.Push(Audio::ResultNotSupported);
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.PushCopyObjects(rendered_event->GetReadableEvent());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void SetRenderingTimeLimit(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
        auto limit = rp.PopRaw<u32>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto& system_ = impl->GetSystem();
 | 
					 | 
				
			||||||
        system_.SetRenderingTimeLimit(limit);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetRenderingTimeLimit(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto& system_ = impl->GetSystem();
 | 
					 | 
				
			||||||
        auto time = system_.GetRenderingTimeLimit();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(time);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void ExecuteAudioRendererRendering(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void SetVoiceDropParameter(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
        auto voice_drop_param{rp.Pop<f32>()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto& system_ = impl->GetSystem();
 | 
					 | 
				
			||||||
        system_.SetVoiceDropParameter(voice_drop_param);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetVoiceDropParameter(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto& system_ = impl->GetSystem();
 | 
					 | 
				
			||||||
        auto voice_drop_param{system_.GetVoiceDropParameter()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(voice_drop_param);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    KernelHelpers::ServiceContext service_context;
 | 
					 | 
				
			||||||
    Kernel::KEvent* rendered_event;
 | 
					 | 
				
			||||||
    Manager& manager;
 | 
					 | 
				
			||||||
    std::unique_ptr<Renderer> impl;
 | 
					 | 
				
			||||||
    Kernel::KProcess& process;
 | 
					 | 
				
			||||||
    Common::ScratchBuffer<u8> output_buffer;
 | 
					 | 
				
			||||||
    Common::ScratchBuffer<u8> performance_buffer;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class IAudioDevice final : public ServiceFramework<IAudioDevice> {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
 | 
					 | 
				
			||||||
                          u32 device_num)
 | 
					 | 
				
			||||||
        : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
 | 
					 | 
				
			||||||
          impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
 | 
					 | 
				
			||||||
          event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
 | 
					 | 
				
			||||||
        static const FunctionInfo functions[] = {
 | 
					 | 
				
			||||||
            {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
 | 
					 | 
				
			||||||
            {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
 | 
					 | 
				
			||||||
            {2, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolume"},
 | 
					 | 
				
			||||||
            {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
 | 
					 | 
				
			||||||
            {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
 | 
					 | 
				
			||||||
            {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
 | 
					 | 
				
			||||||
            {6, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceNameAuto"},
 | 
					 | 
				
			||||||
            {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
 | 
					 | 
				
			||||||
            {8, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolumeAuto"},
 | 
					 | 
				
			||||||
            {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
 | 
					 | 
				
			||||||
            {11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
 | 
					 | 
				
			||||||
            {12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
 | 
					 | 
				
			||||||
            {13, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioOutputDeviceName"},
 | 
					 | 
				
			||||||
            {14, &IAudioDevice::ListAudioOutputDeviceName, "ListAudioOutputDeviceName"},
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        RegisterHandlers(functions);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        event->Signal();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ~IAudioDevice() override {
 | 
					 | 
				
			||||||
        service_context.CloseEvent(event);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    void ListAudioDeviceName(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::vector<AudioDevice::AudioDeviceName> out_names{};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const u32 out_count = impl->ListAudioDeviceName(out_names, in_count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::string out{};
 | 
					 | 
				
			||||||
        for (u32 i = 0; i < out_count; i++) {
 | 
					 | 
				
			||||||
            std::string a{};
 | 
					 | 
				
			||||||
            u32 j = 0;
 | 
					 | 
				
			||||||
            while (out_names[i].name[j] != '\0') {
 | 
					 | 
				
			||||||
                a += out_names[i].name[j];
 | 
					 | 
				
			||||||
                j++;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            out += "\n\t" + a;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ctx.WriteBuffer(out_names);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(out_count);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void SetAudioDeviceOutputVolume(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
        const f32 volume = rp.Pop<f32>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const auto device_name_buffer = ctx.ReadBuffer();
 | 
					 | 
				
			||||||
        const std::string name = Common::StringFromBuffer(device_name_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called. name={}, volume={}", name, volume);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (name == "AudioTvOutput") {
 | 
					 | 
				
			||||||
            impl->SetDeviceVolumes(volume);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetAudioDeviceOutputVolume(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const auto device_name_buffer = ctx.ReadBuffer();
 | 
					 | 
				
			||||||
        const std::string name = Common::StringFromBuffer(device_name_buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called. Name={}", name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        f32 volume{1.0f};
 | 
					 | 
				
			||||||
        if (name == "AudioTvOutput") {
 | 
					 | 
				
			||||||
            volume = impl->GetDeviceVolume(name);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(volume);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetActiveAudioDeviceName(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const auto write_size = ctx.GetWriteBufferSize();
 | 
					 | 
				
			||||||
        std::string out_name{"AudioTvOutput"};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        out_name.resize(write_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ctx.WriteBuffer(out_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void QueryAudioDeviceSystemEvent(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "(STUBBED) called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        event->Signal();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.PushCopyObjects(event->GetReadableEvent());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void GetActiveChannelCount(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const auto& sink{system.AudioCore().GetOutputSink()};
 | 
					 | 
				
			||||||
        u32 channel_count{sink.GetSystemChannels()};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push<u32>(channel_count);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void QueryAudioDeviceInputEvent(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "(STUBBED) called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.PushCopyObjects(event->GetReadableEvent());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void QueryAudioDeviceOutputEvent(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.PushCopyObjects(event->GetReadableEvent());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void ListAudioOutputDeviceName(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
        const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::vector<AudioDevice::AudioDeviceName> out_names{};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::string out{};
 | 
					 | 
				
			||||||
        for (u32 i = 0; i < out_count; i++) {
 | 
					 | 
				
			||||||
            std::string a{};
 | 
					 | 
				
			||||||
            u32 j = 0;
 | 
					 | 
				
			||||||
            while (out_names[i].name[j] != '\0') {
 | 
					 | 
				
			||||||
                a += out_names[i].name[j];
 | 
					 | 
				
			||||||
                j++;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            out += "\n\t" + a;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 3};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ctx.WriteBuffer(out_names);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
        rb.Push(out_count);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    KernelHelpers::ServiceContext service_context;
 | 
					 | 
				
			||||||
    std::unique_ptr<AudioDevice> impl;
 | 
					 | 
				
			||||||
    Kernel::KEvent* event;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AudRenU::AudRenU(Core::System& system_)
 | 
					 | 
				
			||||||
    : ServiceFramework{system_, "audren:u"},
 | 
					 | 
				
			||||||
      service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
 | 
					 | 
				
			||||||
    // clang-format off
 | 
					 | 
				
			||||||
    static const FunctionInfo functions[] = {
 | 
					 | 
				
			||||||
        {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
 | 
					 | 
				
			||||||
        {1, &AudRenU::GetWorkBufferSize, "GetWorkBufferSize"},
 | 
					 | 
				
			||||||
        {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
 | 
					 | 
				
			||||||
        {3, nullptr, "OpenAudioRendererForManualExecution"},
 | 
					 | 
				
			||||||
        {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    // clang-format on
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    RegisterHandlers(functions);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AudRenU::~AudRenU() = default;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    AudioCore::AudioRendererParameterInternal params;
 | 
					 | 
				
			||||||
    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
 | 
					 | 
				
			||||||
    rp.Skip(1, false);
 | 
					 | 
				
			||||||
    auto transfer_memory_size = rp.Pop<u64>();
 | 
					 | 
				
			||||||
    auto applet_resource_user_id = rp.Pop<u64>();
 | 
					 | 
				
			||||||
    auto transfer_memory_handle = ctx.GetCopyHandle(0);
 | 
					 | 
				
			||||||
    auto process_handle = ctx.GetCopyHandle(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(Audio::ResultOutOfSessions);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
 | 
					 | 
				
			||||||
    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto session_id{impl->GetSessionId()};
 | 
					 | 
				
			||||||
    if (session_id == -1) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
 | 
					 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					 | 
				
			||||||
        rb.Push(Audio::ResultOutOfSessions);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
 | 
					 | 
				
			||||||
              impl->GetSessionCount());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
 | 
					 | 
				
			||||||
                                        transfer_memory_size, process_handle, *process,
 | 
					 | 
				
			||||||
                                        applet_resource_user_id, session_id);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AudRenU::GetWorkBufferSize(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    AudioCore::AudioRendererParameterInternal params;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    u64 size{0};
 | 
					 | 
				
			||||||
    auto result = impl->GetWorkBufferSize(params, size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::string output_info{};
 | 
					 | 
				
			||||||
    output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
 | 
					 | 
				
			||||||
    output_info +=
 | 
					 | 
				
			||||||
        fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
 | 
					 | 
				
			||||||
    output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
 | 
					 | 
				
			||||||
                               static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
 | 
					 | 
				
			||||||
    output_info += fmt::format(
 | 
					 | 
				
			||||||
        "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
 | 
					 | 
				
			||||||
        "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
 | 
					 | 
				
			||||||
        "Context {:04X}",
 | 
					 | 
				
			||||||
        params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
 | 
					 | 
				
			||||||
        params.splitter_destinations, params.voices, params.perf_frames,
 | 
					 | 
				
			||||||
        params.external_context_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
 | 
					 | 
				
			||||||
              output_info, size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 4};
 | 
					 | 
				
			||||||
    rb.Push(result);
 | 
					 | 
				
			||||||
    rb.Push<u64>(size);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto applet_resource_user_id = rp.Pop<u64>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_Audio, "called. Applet resource id {}", applet_resource_user_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id,
 | 
					 | 
				
			||||||
                                      ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    LOG_ERROR(Service_Audio, "called. Implement me!");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
 | 
					 | 
				
			||||||
    struct Parameters {
 | 
					 | 
				
			||||||
        u32 revision;
 | 
					 | 
				
			||||||
        u64 applet_resource_user_id;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::RequestParser rp{ctx};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto [revision, applet_resource_user_id] = rp.PopRaw<Parameters>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LOG_DEBUG(Service_Audio, "called. Revision {} Applet resource id {}",
 | 
					 | 
				
			||||||
              AudioCore::GetRevisionNum(revision), applet_resource_user_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    rb.Push(ResultSuccess);
 | 
					 | 
				
			||||||
    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id, revision,
 | 
					 | 
				
			||||||
                                      num_audio_devices++);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace Service::Audio
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user