audio: fetch process object from handle table

master
Liam 2024-01-12 09:35:08 +07:00
parent a4d90a9a64
commit d940974789
8 changed files with 85 additions and 35 deletions

@ -10,6 +10,8 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/hle/kernel/k_process.h"
namespace AudioCore { namespace AudioCore {
using namespace std::literals; using namespace std::literals;
@ -25,7 +27,7 @@ DeviceSession::~DeviceSession() {
} }
Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_format_, Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_format_,
u16 channel_count_, size_t session_id_, u32 handle_, u16 channel_count_, size_t session_id_, Kernel::KProcess* handle_,
u64 applet_resource_user_id_, Sink::StreamType type_) { u64 applet_resource_user_id_, Sink::StreamType type_) {
if (stream) { if (stream) {
Finalize(); Finalize();
@ -36,6 +38,7 @@ Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_for
channel_count = channel_count_; channel_count = channel_count_;
session_id = session_id_; session_id = session_id_;
handle = handle_; handle = handle_;
handle->Open();
applet_resource_user_id = applet_resource_user_id_; applet_resource_user_id = applet_resource_user_id_;
if (type == Sink::StreamType::In) { if (type == Sink::StreamType::In) {
@ -54,6 +57,11 @@ void DeviceSession::Finalize() {
sink->CloseStream(stream); sink->CloseStream(stream);
stream = nullptr; stream = nullptr;
} }
if (handle) {
handle->Close();
handle = nullptr;
}
} }
void DeviceSession::Start() { void DeviceSession::Start() {
@ -91,7 +99,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) {
stream->AppendBuffer(new_buffer, tmp_samples); stream->AppendBuffer(new_buffer, tmp_samples);
} else { } else {
Core::Memory::CpuGuestMemory<s16, Core::Memory::GuestMemoryFlags::UnsafeRead> samples( Core::Memory::CpuGuestMemory<s16, Core::Memory::GuestMemoryFlags::UnsafeRead> samples(
system.ApplicationMemory(), buffer.samples, buffer.size / sizeof(s16)); handle->GetMemory(), buffer.samples, buffer.size / sizeof(s16));
stream->AppendBuffer(new_buffer, samples); stream->AppendBuffer(new_buffer, samples);
} }
} }
@ -100,7 +108,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) {
void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const { void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
if (type == Sink::StreamType::In) { if (type == Sink::StreamType::In) {
auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))}; auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))};
system.ApplicationMemory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size); handle->GetMemory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
} }
} }

@ -20,6 +20,10 @@ struct EventType;
} // namespace Timing } // namespace Timing
} // namespace Core } // namespace Core
namespace Kernel {
class KProcess;
} // namespace Kernel
namespace AudioCore { namespace AudioCore {
namespace Sink { namespace Sink {
@ -44,13 +48,13 @@ public:
* @param sample_format - Sample format for this device's output. * @param sample_format - Sample format for this device's output.
* @param channel_count - Number of channels for this device (2 or 6). * @param channel_count - Number of channels for this device (2 or 6).
* @param session_id - This session's id. * @param session_id - This session's id.
* @param handle - Handle for this device session (unused). * @param handle - Process handle for this device session.
* @param applet_resource_user_id - Applet resource user id for this device session (unused). * @param applet_resource_user_id - Applet resource user id for this device session (unused).
* @param type - Type of this stream (Render, In, Out). * @param type - Type of this stream (Render, In, Out).
* @return Result code for this call. * @return Result code for this call.
*/ */
Result Initialize(std::string_view name, SampleFormat sample_format, u16 channel_count, Result Initialize(std::string_view name, SampleFormat sample_format, u16 channel_count,
size_t session_id, u32 handle, u64 applet_resource_user_id, size_t session_id, Kernel::KProcess* handle, u64 applet_resource_user_id,
Sink::StreamType type); Sink::StreamType type);
/** /**
@ -137,8 +141,8 @@ private:
u16 channel_count{}; u16 channel_count{};
/// Session id of this device session /// Session id of this device session
size_t session_id{}; size_t session_id{};
/// Handle of this device session /// Process handle of device memory owner
u32 handle{}; Kernel::KProcess* handle{};
/// Applet resource user id of this device session /// Applet resource user id of this device session
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
/// Total number of samples played by this device session /// Total number of samples played by this device session

@ -57,7 +57,7 @@ Result System::IsConfigValid(const std::string_view device_name,
} }
Result System::Initialize(std::string device_name, const AudioInParameter& in_params, Result System::Initialize(std::string device_name, const AudioInParameter& in_params,
const u32 handle_, const u64 applet_resource_user_id_) { Kernel::KProcess* handle_, const u64 applet_resource_user_id_) {
auto result{IsConfigValid(device_name, in_params)}; auto result{IsConfigValid(device_name, in_params)};
if (result.IsError()) { if (result.IsError()) {
return result; return result;

@ -19,7 +19,8 @@ class System;
namespace Kernel { namespace Kernel {
class KEvent; class KEvent;
} class KProcess;
} // namespace Kernel
namespace AudioCore::AudioIn { namespace AudioCore::AudioIn {
@ -93,12 +94,12 @@ public:
* *
* @param device_name - The name of the requested input device. * @param device_name - The name of the requested input device.
* @param in_params - Input parameters, see AudioInParameter. * @param in_params - Input parameters, see AudioInParameter.
* @param handle - Unused. * @param handle - Process handle.
* @param applet_resource_user_id - Unused. * @param applet_resource_user_id - Unused.
* @return Result code. * @return Result code.
*/ */
Result Initialize(std::string device_name, const AudioInParameter& in_params, u32 handle, Result Initialize(std::string device_name, const AudioInParameter& in_params,
u64 applet_resource_user_id); Kernel::KProcess* handle, u64 applet_resource_user_id);
/** /**
* Start this system. * Start this system.
@ -244,8 +245,8 @@ public:
private: private:
/// Core system /// Core system
Core::System& system; Core::System& system;
/// (Unused) /// Process handle
u32 handle{}; Kernel::KProcess* handle{};
/// (Unused) /// (Unused)
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
/// Buffer event, signalled when a buffer is ready /// Buffer event, signalled when a buffer is ready

@ -48,8 +48,8 @@ Result System::IsConfigValid(std::string_view device_name,
return Service::Audio::ResultInvalidChannelCount; return Service::Audio::ResultInvalidChannelCount;
} }
Result System::Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle_, Result System::Initialize(std::string device_name, const AudioOutParameter& in_params,
u64 applet_resource_user_id_) { Kernel::KProcess* handle_, u64 applet_resource_user_id_) {
auto result = IsConfigValid(device_name, in_params); auto result = IsConfigValid(device_name, in_params);
if (result.IsError()) { if (result.IsError()) {
return result; return result;

@ -19,7 +19,8 @@ class System;
namespace Kernel { namespace Kernel {
class KEvent; class KEvent;
} class KProcess;
} // namespace Kernel
namespace AudioCore::AudioOut { namespace AudioCore::AudioOut {
@ -84,12 +85,12 @@ public:
* *
* @param device_name - The name of the requested output device. * @param device_name - The name of the requested output device.
* @param in_params - Input parameters, see AudioOutParameter. * @param in_params - Input parameters, see AudioOutParameter.
* @param handle - Unused. * @param handle - Process handle.
* @param applet_resource_user_id - Unused. * @param applet_resource_user_id - Unused.
* @return Result code. * @return Result code.
*/ */
Result Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle, Result Initialize(std::string device_name, const AudioOutParameter& in_params,
u64 applet_resource_user_id); Kernel::KProcess* handle, u64 applet_resource_user_id);
/** /**
* Start this system. * Start this system.
@ -228,8 +229,8 @@ public:
private: private:
/// Core system /// Core system
Core::System& system; Core::System& system;
/// (Unused) /// Process handle
u32 handle{}; Kernel::KProcess* handle{};
/// (Unused) /// (Unused)
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
/// Buffer event, signalled when a buffer is ready /// Buffer event, signalled when a buffer is ready

@ -18,11 +18,11 @@ using namespace AudioCore::AudioIn;
class IAudioIn final : public ServiceFramework<IAudioIn> { class IAudioIn final : public ServiceFramework<IAudioIn> {
public: public:
explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id, explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioInParameter& in_params, u32 handle, const std::string& device_name, const AudioInParameter& in_params,
u64 applet_resource_user_id) Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioIn"}, : ServiceFramework{system_, "IAudioIn"},
service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")}, service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")},
impl{std::make_shared<In>(system_, manager, event, session_id)} { process{handle}, impl{std::make_shared<In>(system_, manager, event, session_id)} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IAudioIn::GetAudioInState, "GetAudioInState"}, {0, &IAudioIn::GetAudioInState, "GetAudioInState"},
@ -45,6 +45,8 @@ public:
RegisterHandlers(functions); RegisterHandlers(functions);
process->Open();
if (impl->GetSystem() if (impl->GetSystem()
.Initialize(device_name, in_params, handle, applet_resource_user_id) .Initialize(device_name, in_params, handle, applet_resource_user_id)
.IsError()) { .IsError()) {
@ -55,6 +57,7 @@ public:
~IAudioIn() override { ~IAudioIn() override {
impl->Free(); impl->Free();
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close();
} }
[[nodiscard]] std::shared_ptr<In> GetImpl() { [[nodiscard]] std::shared_ptr<In> GetImpl() {
@ -196,6 +199,7 @@ private:
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event; Kernel::KEvent* event;
Kernel::KProcess* process;
std::shared_ptr<AudioCore::AudioIn::In> impl; std::shared_ptr<AudioCore::AudioIn::In> impl;
Common::ScratchBuffer<u64> released_buffer; Common::ScratchBuffer<u64> released_buffer;
}; };
@ -267,6 +271,14 @@ void AudInU::OpenAudioIn(HLERequestContext& ctx) {
auto device_name = Common::StringFromBuffer(device_name_data); auto device_name = Common::StringFromBuffer(device_name_data);
auto handle{ctx.GetCopyHandle(0)}; 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;
}
std::scoped_lock l{impl->mutex}; std::scoped_lock l{impl->mutex};
auto link{impl->LinkToManager()}; auto link{impl->LinkToManager()};
if (link.IsError()) { if (link.IsError()) {
@ -287,8 +299,9 @@ void AudInU::OpenAudioIn(HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, auto audio_in =
in_params, handle, applet_resource_user_id); std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
process.GetPointerUnsafe(), applet_resource_user_id);
impl->sessions[new_session_id] = audio_in->GetImpl(); impl->sessions[new_session_id] = audio_in->GetImpl();
impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
@ -318,6 +331,14 @@ void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
auto device_name = Common::StringFromBuffer(device_name_data); auto device_name = Common::StringFromBuffer(device_name_data);
auto handle{ctx.GetCopyHandle(0)}; 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;
}
std::scoped_lock l{impl->mutex}; std::scoped_lock l{impl->mutex};
auto link{impl->LinkToManager()}; auto link{impl->LinkToManager()};
if (link.IsError()) { if (link.IsError()) {
@ -338,8 +359,9 @@ void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, auto audio_in =
in_params, handle, applet_resource_user_id); std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
process.GetPointerUnsafe(), applet_resource_user_id);
impl->sessions[new_session_id] = audio_in->GetImpl(); impl->sessions[new_session_id] = audio_in->GetImpl();
impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id; impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;

@ -26,9 +26,10 @@ class IAudioOut final : public ServiceFramework<IAudioOut> {
public: public:
explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
size_t session_id, const std::string& device_name, size_t session_id, const std::string& device_name,
const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) const AudioOutParameter& in_params, Kernel::KProcess* handle,
u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")}, event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
// clang-format off // clang-format off
@ -50,11 +51,14 @@ public:
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
process->Open();
} }
~IAudioOut() override { ~IAudioOut() override {
impl->Free(); impl->Free();
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close();
} }
[[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() { [[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
@ -206,6 +210,7 @@ private:
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event; Kernel::KEvent* event;
Kernel::KProcess* process;
std::shared_ptr<AudioCore::AudioOut::Out> impl; std::shared_ptr<AudioCore::AudioOut::Out> impl;
Common::ScratchBuffer<u64> released_buffer; Common::ScratchBuffer<u64> released_buffer;
}; };
@ -257,6 +262,14 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
auto device_name = Common::StringFromBuffer(device_name_data); auto device_name = Common::StringFromBuffer(device_name_data);
auto handle{ctx.GetCopyHandle(0)}; 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()}; auto link{impl->LinkToManager()};
if (link.IsError()) { if (link.IsError()) {
LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager"); LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager");
@ -276,10 +289,11 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, auto audio_out =
in_params, handle, applet_resource_user_id); std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, in_params,
result = audio_out->GetImpl()->GetSystem().Initialize(device_name, in_params, handle, process.GetPointerUnsafe(), applet_resource_user_id);
applet_resource_user_id); result = audio_out->GetImpl()->GetSystem().Initialize(
device_name, in_params, process.GetPointerUnsafe(), applet_resource_user_id);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!"); LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};