6 changed files with 151 additions and 159 deletions
-
4src/core/CMakeLists.txt
-
4src/core/hle/service/audio/audio.cpp
-
103src/core/hle/service/audio/audio_out_manager.cpp
-
44src/core/hle/service/audio/audio_out_manager.h
-
118src/core/hle/service/audio/audout_u.cpp
-
37src/core/hle/service/audio/audout_u.h
@ -0,0 +1,103 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
|||
#include "common/string_util.h"
|
|||
#include "core/hle/service/audio/audio_out.h"
|
|||
#include "core/hle/service/audio/audio_out_manager.h"
|
|||
#include "core/hle/service/cmif_serialization.h"
|
|||
#include "core/memory.h"
|
|||
|
|||
namespace Service::Audio { |
|||
using namespace AudioCore::AudioOut; |
|||
|
|||
IAudioOutManager::IAudioOutManager(Core::System& system_) |
|||
: ServiceFramework{system_, "audout:u"}, impl{std::make_unique<Manager>(system_)} { |
|||
// clang-format off
|
|||
static const FunctionInfo functions[] = { |
|||
{0, C<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"}, |
|||
{1, C<&IAudioOutManager::OpenAudioOut>, "OpenAudioOut"}, |
|||
{2, C<&IAudioOutManager::ListAudioOutsAuto>, "ListAudioOutsAuto"}, |
|||
{3, C<&IAudioOutManager::OpenAudioOutAuto>, "OpenAudioOutAuto"}, |
|||
}; |
|||
// clang-format on
|
|||
|
|||
RegisterHandlers(functions); |
|||
} |
|||
|
|||
IAudioOutManager::~IAudioOutManager() = default; |
|||
|
|||
Result IAudioOutManager::ListAudioOuts( |
|||
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs, Out<u32> out_count) { |
|||
R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count)); |
|||
} |
|||
|
|||
Result IAudioOutManager::OpenAudioOut(Out<AudioOutParameterInternal> out_parameter_internal, |
|||
Out<SharedPointer<IAudioOut>> out_audio_out, |
|||
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name, |
|||
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name, |
|||
AudioOutParameter parameter, |
|||
InCopyHandle<Kernel::KProcess> process_handle, |
|||
ClientAppletResourceUserId aruid) { |
|||
R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name, |
|||
parameter, process_handle, aruid)); |
|||
} |
|||
|
|||
Result IAudioOutManager::ListAudioOutsAuto( |
|||
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs, Out<u32> out_count) { |
|||
if (!out_audio_outs.empty()) { |
|||
out_audio_outs[0] = AudioDeviceName("DeviceOut"); |
|||
*out_count = 1; |
|||
LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut"); |
|||
} else { |
|||
*out_count = 0; |
|||
LOG_DEBUG(Service_Audio, "called. Empty buffer passed in."); |
|||
} |
|||
|
|||
R_SUCCEED(); |
|||
} |
|||
|
|||
Result IAudioOutManager::OpenAudioOutAuto( |
|||
Out<AudioOutParameterInternal> out_parameter_internal, |
|||
Out<SharedPointer<IAudioOut>> out_audio_out, |
|||
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name, |
|||
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioOutParameter parameter, |
|||
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) { |
|||
if (!process_handle) { |
|||
LOG_ERROR(Service_Audio, "Failed to get process handle"); |
|||
R_THROW(ResultUnknown); |
|||
} |
|||
if (name.empty() || out_name.empty()) { |
|||
LOG_ERROR(Service_Audio, "Invalid buffers"); |
|||
R_THROW(ResultUnknown); |
|||
} |
|||
|
|||
size_t new_session_id{}; |
|||
R_TRY(impl->LinkToManager()); |
|||
R_TRY(impl->AcquireSessionId(new_session_id)); |
|||
|
|||
const auto name_buffer = std::span(reinterpret_cast<const u8*>(name[0].name.data()), 0x100); |
|||
const auto device_name = Common::StringFromBuffer(name_buffer); |
|||
|
|||
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id, |
|||
impl->num_free_sessions); |
|||
|
|||
auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, |
|||
parameter, process_handle.Get(), aruid.pid); |
|||
R_TRY(audio_out->GetImpl()->GetSystem().Initialize(device_name, parameter, process_handle.Get(), |
|||
aruid.pid)); |
|||
|
|||
*out_audio_out = audio_out; |
|||
impl->sessions[new_session_id] = audio_out->GetImpl(); |
|||
impl->applet_resource_user_ids[new_session_id] = aruid.pid; |
|||
|
|||
auto& out_system = impl->sessions[new_session_id]->GetSystem(); |
|||
*out_parameter_internal = |
|||
AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(), |
|||
.channel_count = out_system.GetChannelCount(), |
|||
.sample_format = static_cast<u32>(out_system.GetSampleFormat()), |
|||
.state = static_cast<u32>(out_system.GetState())}; |
|||
|
|||
R_SUCCEED(); |
|||
} |
|||
|
|||
} // namespace Service::Audio
|
|||
@ -0,0 +1,44 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include "audio_core/audio_out_manager.h" |
|||
#include "audio_core/out/audio_out.h" |
|||
#include "core/hle/service/cmif_types.h" |
|||
#include "core/hle/service/service.h" |
|||
|
|||
namespace Service::Audio { |
|||
|
|||
using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName; |
|||
class IAudioOut; |
|||
|
|||
class IAudioOutManager final : public ServiceFramework<IAudioOutManager> { |
|||
public: |
|||
explicit IAudioOutManager(Core::System& system_); |
|||
~IAudioOutManager() override; |
|||
|
|||
private: |
|||
Result ListAudioOuts(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs, |
|||
Out<u32> out_count); |
|||
Result OpenAudioOut(Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal, |
|||
Out<SharedPointer<IAudioOut>> out_audio_out, |
|||
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name, |
|||
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name, |
|||
AudioCore::AudioOut::AudioOutParameter parameter, |
|||
InCopyHandle<Kernel::KProcess> process_handle, |
|||
ClientAppletResourceUserId aruid); |
|||
Result ListAudioOutsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs, |
|||
Out<u32> out_count); |
|||
Result OpenAudioOutAuto( |
|||
Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal, |
|||
Out<SharedPointer<IAudioOut>> out_audio_out, |
|||
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name, |
|||
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, |
|||
AudioCore::AudioOut::AudioOutParameter parameter, |
|||
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid); |
|||
|
|||
std::unique_ptr<AudioCore::AudioOut::Manager> impl; |
|||
}; |
|||
|
|||
} // namespace Service::Audio |
|||
@ -1,118 +0,0 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
|||
#include "common/string_util.h"
|
|||
#include "core/hle/service/audio/audio_out.h"
|
|||
#include "core/hle/service/audio/audout_u.h"
|
|||
#include "core/hle/service/ipc_helpers.h"
|
|||
#include "core/memory.h"
|
|||
|
|||
namespace Service::Audio { |
|||
using namespace AudioCore::AudioOut; |
|||
|
|||
AudOutU::AudOutU(Core::System& system_) |
|||
: ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"}, |
|||
impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} { |
|||
// clang-format off
|
|||
static const FunctionInfo functions[] = { |
|||
{0, &AudOutU::ListAudioOuts, "ListAudioOuts"}, |
|||
{1, &AudOutU::OpenAudioOut, "OpenAudioOut"}, |
|||
{2, &AudOutU::ListAudioOuts, "ListAudioOutsAuto"}, |
|||
{3, &AudOutU::OpenAudioOut, "OpenAudioOutAuto"}, |
|||
}; |
|||
// clang-format on
|
|||
|
|||
RegisterHandlers(functions); |
|||
} |
|||
|
|||
AudOutU::~AudOutU() = default; |
|||
|
|||
void AudOutU::ListAudioOuts(HLERequestContext& ctx) { |
|||
using namespace AudioCore::Renderer; |
|||
|
|||
std::scoped_lock l{impl->mutex}; |
|||
|
|||
const auto write_count = |
|||
static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>()); |
|||
std::vector<AudioDevice::AudioDeviceName> device_names{}; |
|||
if (write_count > 0) { |
|||
device_names.emplace_back("DeviceOut"); |
|||
LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut"); |
|||
} else { |
|||
LOG_DEBUG(Service_Audio, "called. Empty buffer passed in."); |
|||
} |
|||
|
|||
ctx.WriteBuffer(device_names); |
|||
|
|||
IPC::ResponseBuilder rb{ctx, 3}; |
|||
rb.Push(ResultSuccess); |
|||
rb.Push<u32>(static_cast<u32>(device_names.size())); |
|||
} |
|||
|
|||
void AudOutU::OpenAudioOut(HLERequestContext& ctx) { |
|||
IPC::RequestParser rp{ctx}; |
|||
auto in_params{rp.PopRaw<AudioOutParameter>()}; |
|||
auto applet_resource_user_id{rp.PopRaw<u64>()}; |
|||
const auto device_name_data{ctx.ReadBuffer()}; |
|||
auto device_name = Common::StringFromBuffer(device_name_data); |
|||
auto handle{ctx.GetCopyHandle(0)}; |
|||
|
|||
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)}; |
|||
if (process.IsNull()) { |
|||
LOG_ERROR(Service_Audio, "Failed to get process handle"); |
|||
IPC::ResponseBuilder rb{ctx, 2}; |
|||
rb.Push(ResultUnknown); |
|||
return; |
|||
} |
|||
|
|||
auto link{impl->LinkToManager()}; |
|||
if (link.IsError()) { |
|||
LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager"); |
|||
IPC::ResponseBuilder rb{ctx, 2}; |
|||
rb.Push(link); |
|||
return; |
|||
} |
|||
|
|||
size_t new_session_id{}; |
|||
auto result{impl->AcquireSessionId(new_session_id)}; |
|||
if (result.IsError()) { |
|||
IPC::ResponseBuilder rb{ctx, 2}; |
|||
rb.Push(result); |
|||
return; |
|||
} |
|||
|
|||
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id, |
|||
impl->num_free_sessions); |
|||
|
|||
auto audio_out = |
|||
std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, in_params, |
|||
process.GetPointerUnsafe(), applet_resource_user_id); |
|||
result = audio_out->GetImpl()->GetSystem().Initialize( |
|||
device_name, in_params, process.GetPointerUnsafe(), applet_resource_user_id); |
|||
if (result.IsError()) { |
|||
LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!"); |
|||
IPC::ResponseBuilder rb{ctx, 2}; |
|||
rb.Push(result); |
|||
return; |
|||
} |
|||
|
|||
impl->sessions[new_session_id] = audio_out->GetImpl(); |
|||
impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; |
|||
|
|||
auto& out_system = impl->sessions[new_session_id]->GetSystem(); |
|||
AudioOutParameterInternal out_params{.sample_rate = out_system.GetSampleRate(), |
|||
.channel_count = out_system.GetChannelCount(), |
|||
.sample_format = |
|||
static_cast<u32>(out_system.GetSampleFormat()), |
|||
.state = static_cast<u32>(out_system.GetState())}; |
|||
|
|||
IPC::ResponseBuilder rb{ctx, 6, 0, 1}; |
|||
|
|||
ctx.WriteBuffer(out_system.GetName()); |
|||
|
|||
rb.Push(ResultSuccess); |
|||
rb.PushRaw<AudioOutParameterInternal>(out_params); |
|||
rb.PushIpcInterface<IAudioOut>(audio_out); |
|||
} |
|||
|
|||
} // namespace Service::Audio
|
|||
@ -1,37 +0,0 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include "audio_core/audio_out_manager.h" |
|||
#include "audio_core/out/audio_out.h" |
|||
#include "core/hle/service/kernel_helpers.h" |
|||
#include "core/hle/service/service.h" |
|||
|
|||
namespace Core { |
|||
class System; |
|||
} |
|||
|
|||
namespace AudioCore::AudioOut { |
|||
class Manager; |
|||
class Out; |
|||
} // namespace AudioCore::AudioOut |
|||
|
|||
namespace Service::Audio { |
|||
|
|||
class IAudioOut; |
|||
|
|||
class AudOutU final : public ServiceFramework<AudOutU> { |
|||
public: |
|||
explicit AudOutU(Core::System& system_); |
|||
~AudOutU() override; |
|||
|
|||
private: |
|||
void ListAudioOuts(HLERequestContext& ctx); |
|||
void OpenAudioOut(HLERequestContext& ctx); |
|||
|
|||
KernelHelpers::ServiceContext service_context; |
|||
std::unique_ptr<AudioCore::AudioOut::Manager> impl; |
|||
}; |
|||
|
|||
} // namespace Service::Audio |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue