mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-12-25 02:42:41 -06:00
Merge pull request #12659 from liamwhite/audio-memory
audio: fetch process object from handle table
This commit is contained in:
commit
34db13486a
8 changed files with 85 additions and 35 deletions
|
@ -10,6 +10,8 @@
|
|||
#include "core/core_timing.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
using namespace std::literals;
|
||||
|
@ -25,7 +27,7 @@ DeviceSession::~DeviceSession() {
|
|||
}
|
||||
|
||||
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_) {
|
||||
if (stream) {
|
||||
Finalize();
|
||||
|
@ -36,6 +38,7 @@ Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_for
|
|||
channel_count = channel_count_;
|
||||
session_id = session_id_;
|
||||
handle = handle_;
|
||||
handle->Open();
|
||||
applet_resource_user_id = applet_resource_user_id_;
|
||||
|
||||
if (type == Sink::StreamType::In) {
|
||||
|
@ -54,6 +57,11 @@ void DeviceSession::Finalize() {
|
|||
sink->CloseStream(stream);
|
||||
stream = nullptr;
|
||||
}
|
||||
|
||||
if (handle) {
|
||||
handle->Close();
|
||||
handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceSession::Start() {
|
||||
|
@ -91,7 +99,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) {
|
|||
stream->AppendBuffer(new_buffer, tmp_samples);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +108,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) {
|
|||
void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
|
||||
if (type == Sink::StreamType::In) {
|
||||
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 Core
|
||||
|
||||
namespace Kernel {
|
||||
class KProcess;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
namespace Sink {
|
||||
|
@ -44,13 +48,13 @@ public:
|
|||
* @param sample_format - Sample format for this device's output.
|
||||
* @param channel_count - Number of channels for this device (2 or 6).
|
||||
* @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 type - Type of this stream (Render, In, Out).
|
||||
* @return Result code for this call.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
|
@ -137,8 +141,8 @@ private:
|
|||
u16 channel_count{};
|
||||
/// Session id of this device session
|
||||
size_t session_id{};
|
||||
/// Handle of this device session
|
||||
u32 handle{};
|
||||
/// Process handle of device memory owner
|
||||
Kernel::KProcess* handle{};
|
||||
/// Applet resource user id of this device session
|
||||
u64 applet_resource_user_id{};
|
||||
/// 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,
|
||||
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)};
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
|
|
|
@ -19,7 +19,8 @@ class System;
|
|||
|
||||
namespace Kernel {
|
||||
class KEvent;
|
||||
}
|
||||
class KProcess;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace AudioCore::AudioIn {
|
||||
|
||||
|
@ -93,12 +94,12 @@ public:
|
|||
*
|
||||
* @param device_name - The name of the requested input device.
|
||||
* @param in_params - Input parameters, see AudioInParameter.
|
||||
* @param handle - Unused.
|
||||
* @param handle - Process handle.
|
||||
* @param applet_resource_user_id - Unused.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result Initialize(std::string device_name, const AudioInParameter& in_params, u32 handle,
|
||||
u64 applet_resource_user_id);
|
||||
Result Initialize(std::string device_name, const AudioInParameter& in_params,
|
||||
Kernel::KProcess* handle, u64 applet_resource_user_id);
|
||||
|
||||
/**
|
||||
* Start this system.
|
||||
|
@ -244,8 +245,8 @@ public:
|
|||
private:
|
||||
/// Core system
|
||||
Core::System& system;
|
||||
/// (Unused)
|
||||
u32 handle{};
|
||||
/// Process handle
|
||||
Kernel::KProcess* handle{};
|
||||
/// (Unused)
|
||||
u64 applet_resource_user_id{};
|
||||
/// Buffer event, signalled when a buffer is ready
|
||||
|
|
|
@ -48,8 +48,8 @@ Result System::IsConfigValid(std::string_view device_name,
|
|||
return Service::Audio::ResultInvalidChannelCount;
|
||||
}
|
||||
|
||||
Result System::Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle_,
|
||||
u64 applet_resource_user_id_) {
|
||||
Result System::Initialize(std::string device_name, const AudioOutParameter& in_params,
|
||||
Kernel::KProcess* handle_, u64 applet_resource_user_id_) {
|
||||
auto result = IsConfigValid(device_name, in_params);
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
|
|
|
@ -19,7 +19,8 @@ class System;
|
|||
|
||||
namespace Kernel {
|
||||
class KEvent;
|
||||
}
|
||||
class KProcess;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace AudioCore::AudioOut {
|
||||
|
||||
|
@ -84,12 +85,12 @@ public:
|
|||
*
|
||||
* @param device_name - The name of the requested output device.
|
||||
* @param in_params - Input parameters, see AudioOutParameter.
|
||||
* @param handle - Unused.
|
||||
* @param handle - Process handle.
|
||||
* @param applet_resource_user_id - Unused.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle,
|
||||
u64 applet_resource_user_id);
|
||||
Result Initialize(std::string device_name, const AudioOutParameter& in_params,
|
||||
Kernel::KProcess* handle, u64 applet_resource_user_id);
|
||||
|
||||
/**
|
||||
* Start this system.
|
||||
|
@ -228,8 +229,8 @@ public:
|
|||
private:
|
||||
/// Core system
|
||||
Core::System& system;
|
||||
/// (Unused)
|
||||
u32 handle{};
|
||||
/// Process handle
|
||||
Kernel::KProcess* handle{};
|
||||
/// (Unused)
|
||||
u64 applet_resource_user_id{};
|
||||
/// Buffer event, signalled when a buffer is ready
|
||||
|
|
|
@ -18,11 +18,11 @@ using namespace AudioCore::AudioIn;
|
|||
class IAudioIn final : public ServiceFramework<IAudioIn> {
|
||||
public:
|
||||
explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
|
||||
const std::string& device_name, const AudioInParameter& in_params, u32 handle,
|
||||
u64 applet_resource_user_id)
|
||||
const std::string& device_name, const AudioInParameter& in_params,
|
||||
Kernel::KProcess* handle, u64 applet_resource_user_id)
|
||||
: ServiceFramework{system_, "IAudioIn"},
|
||||
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
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IAudioIn::GetAudioInState, "GetAudioInState"},
|
||||
|
@ -45,6 +45,8 @@ public:
|
|||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
process->Open();
|
||||
|
||||
if (impl->GetSystem()
|
||||
.Initialize(device_name, in_params, handle, applet_resource_user_id)
|
||||
.IsError()) {
|
||||
|
@ -55,6 +57,7 @@ public:
|
|||
~IAudioIn() override {
|
||||
impl->Free();
|
||||
service_context.CloseEvent(event);
|
||||
process->Close();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<In> GetImpl() {
|
||||
|
@ -196,6 +199,7 @@ private:
|
|||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* event;
|
||||
Kernel::KProcess* process;
|
||||
std::shared_ptr<AudioCore::AudioIn::In> impl;
|
||||
Common::ScratchBuffer<u64> released_buffer;
|
||||
};
|
||||
|
@ -267,6 +271,14 @@ void AudInU::OpenAudioIn(HLERequestContext& ctx) {
|
|||
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;
|
||||
}
|
||||
|
||||
std::scoped_lock l{impl->mutex};
|
||||
auto link{impl->LinkToManager()};
|
||||
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,
|
||||
impl->num_free_sessions);
|
||||
|
||||
auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
|
||||
in_params, handle, applet_resource_user_id);
|
||||
auto audio_in =
|
||||
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->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 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};
|
||||
auto link{impl->LinkToManager()};
|
||||
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,
|
||||
impl->num_free_sessions);
|
||||
|
||||
auto audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
|
||||
in_params, handle, applet_resource_user_id);
|
||||
auto audio_in =
|
||||
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->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
|
||||
|
||||
|
|
|
@ -26,9 +26,10 @@ class IAudioOut final : public ServiceFramework<IAudioOut> {
|
|||
public:
|
||||
explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
|
||||
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"},
|
||||
event{service_context.CreateEvent("AudioOutEvent")},
|
||||
event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
|
||||
impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
|
||||
|
||||
// clang-format off
|
||||
|
@ -50,11 +51,14 @@ public:
|
|||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
||||
process->Open();
|
||||
}
|
||||
|
||||
~IAudioOut() override {
|
||||
impl->Free();
|
||||
service_context.CloseEvent(event);
|
||||
process->Close();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
|
||||
|
@ -206,6 +210,7 @@ private:
|
|||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* event;
|
||||
Kernel::KProcess* process;
|
||||
std::shared_ptr<AudioCore::AudioOut::Out> impl;
|
||||
Common::ScratchBuffer<u64> released_buffer;
|
||||
};
|
||||
|
@ -257,6 +262,14 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
|
|||
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");
|
||||
|
@ -276,10 +289,11 @@ void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
|
|||
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, handle, applet_resource_user_id);
|
||||
result = audio_out->GetImpl()->GetSystem().Initialize(device_name, in_params, handle,
|
||||
applet_resource_user_id);
|
||||
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};
|
||||
|
|
Loading…
Reference in a new issue