Merge pull request #12659 from liamwhite/audio-memory
audio: fetch process object from handle table
This commit is contained in:
		@@ -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};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user