فهرست منبع

audio: rewrite IAudioInManager

Liam 2 سال پیش
والد
کامیت
2a2c92f181

+ 3 - 4
src/audio_core/audio_in_manager.cpp

@@ -73,16 +73,15 @@ void Manager::BufferReleaseAndRegister() {
     }
     }
 }
 }
 
 
-u32 Manager::GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names,
-                            [[maybe_unused]] const u32 max_count,
+u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names,
                             [[maybe_unused]] const bool filter) {
                             [[maybe_unused]] const bool filter) {
     std::scoped_lock l{mutex};
     std::scoped_lock l{mutex};
 
 
     LinkToManager();
     LinkToManager();
 
 
     auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
     auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
-    if (input_devices.size() > 1) {
-        names.emplace_back("Uac");
+    if (!input_devices.empty() && !names.empty()) {
+        names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
         return 1;
         return 1;
     }
     }
     return 0;
     return 0;

+ 1 - 3
src/audio_core/audio_in_manager.h

@@ -60,13 +60,11 @@ public:
      * Get a list of audio in device names.
      * Get a list of audio in device names.
      *
      *
      * @param names     - Output container to write names to.
      * @param names     - Output container to write names to.
-     * @param max_count - Maximum number of device names to write. Unused
      * @param filter    - Should the list be filtered? Unused.
      * @param filter    - Should the list be filtered? Unused.
      *
      *
      * @return Number of names written.
      * @return Number of names written.
      */
      */
-    u32 GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, u32 max_count,
-                       bool filter);
+    u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
 
 
     /// Core system
     /// Core system
     Core::System& system;
     Core::System& system;

+ 2 - 2
src/core/CMakeLists.txt

@@ -489,8 +489,8 @@ 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/audin_u.cpp
-    hle/service/audio/audin_u.h
+    hle/service/audio/audio_in_manager.cpp
+    hle/service/audio/audio_in_manager.h
     hle/service/audio/audio_in.cpp
     hle/service/audio/audio_in.cpp
     hle/service/audio/audio_in.h
     hle/service/audio/audio_in.h
     hle/service/audio/audio.cpp
     hle/service/audio/audio.cpp

+ 0 - 198
src/core/hle/service/audio/audin_u.cpp

@@ -1,198 +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/audin_u.h"
-#include "core/hle/service/audio/audio_in.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::Audio {
-using namespace AudioCore::AudioIn;
-
-AudInU::AudInU(Core::System& system_)
-    : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"},
-      impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &AudInU::ListAudioIns, "ListAudioIns"},
-        {1, &AudInU::OpenAudioIn, "OpenAudioIn"},
-        {2, &AudInU::ListAudioIns, "ListAudioInsAuto"},
-        {3, &AudInU::OpenAudioIn, "OpenAudioInAuto"},
-        {4, &AudInU::ListAudioInsAutoFiltered, "ListAudioInsAutoFiltered"},
-        {5, &AudInU::OpenAudioInProtocolSpecified, "OpenAudioInProtocolSpecified"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-AudInU::~AudInU() = default;
-
-void AudInU::ListAudioIns(HLERequestContext& ctx) {
-    using namespace AudioCore::Renderer;
-
-    LOG_DEBUG(Service_Audio, "called");
-
-    const auto write_count =
-        static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
-    std::vector<AudioDevice::AudioDeviceName> device_names{};
-
-    u32 out_count{0};
-    if (write_count > 0) {
-        out_count = impl->GetDeviceNames(device_names, write_count, false);
-        ctx.WriteBuffer(device_names);
-    }
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(out_count);
-}
-
-void AudInU::ListAudioInsAutoFiltered(HLERequestContext& ctx) {
-    using namespace AudioCore::Renderer;
-
-    LOG_DEBUG(Service_Audio, "called");
-
-    const auto write_count =
-        static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
-    std::vector<AudioDevice::AudioDeviceName> device_names{};
-
-    u32 out_count{0};
-    if (write_count > 0) {
-        out_count = impl->GetDeviceNames(device_names, write_count, true);
-        ctx.WriteBuffer(device_names);
-    }
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(out_count);
-}
-
-void AudInU::OpenAudioIn(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    auto in_params{rp.PopRaw<AudioInParameter>()};
-    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;
-    }
-
-    std::scoped_lock l{impl->mutex};
-    auto link{impl->LinkToManager()};
-    if (link.IsError()) {
-        LOG_ERROR(Service_Audio, "Failed to link Audio In 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 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,
-                                   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;
-
-    auto& out_system = impl->sessions[new_session_id]->GetSystem();
-    AudioInParameterInternal 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};
-
-    std::string out_name{out_system.GetName()};
-    ctx.WriteBuffer(out_name);
-
-    rb.Push(ResultSuccess);
-    rb.PushRaw<AudioInParameterInternal>(out_params);
-    rb.PushIpcInterface<IAudioIn>(audio_in);
-}
-
-void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    auto protocol_specified{rp.PopRaw<u64>()};
-    auto in_params{rp.PopRaw<AudioInParameter>()};
-    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;
-    }
-
-    std::scoped_lock l{impl->mutex};
-    auto link{impl->LinkToManager()};
-    if (link.IsError()) {
-        LOG_ERROR(Service_Audio, "Failed to link Audio In 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 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,
-                                   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;
-
-    auto& out_system = impl->sessions[new_session_id]->GetSystem();
-    AudioInParameterInternal 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};
-
-    std::string out_name{out_system.GetName()};
-    if (protocol_specified == 0) {
-        if (out_system.IsUac()) {
-            out_name = "UacIn";
-        } else {
-            out_name = "DeviceIn";
-        }
-    }
-
-    ctx.WriteBuffer(out_name);
-
-    rb.Push(ResultSuccess);
-    rb.PushRaw<AudioInParameterInternal>(out_params);
-    rb.PushIpcInterface<IAudioIn>(audio_in);
-}
-
-} // namespace Service::Audio

+ 0 - 38
src/core/hle/service/audio/audin_u.h

@@ -1,38 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "audio_core/audio_in_manager.h"
-#include "audio_core/in/audio_in.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace AudioCore::AudioOut {
-class Manager;
-class In;
-} // namespace AudioCore::AudioOut
-
-namespace Service::Audio {
-
-class AudInU final : public ServiceFramework<AudInU> {
-public:
-    explicit AudInU(Core::System& system_);
-    ~AudInU() override;
-
-private:
-    void ListAudioIns(HLERequestContext& ctx);
-    void ListAudioInsAutoFiltered(HLERequestContext& ctx);
-    void OpenInOutImpl(HLERequestContext& ctx);
-    void OpenAudioIn(HLERequestContext& ctx);
-    void OpenAudioInProtocolSpecified(HLERequestContext& ctx);
-
-    KernelHelpers::ServiceContext service_context;
-    std::unique_ptr<AudioCore::AudioIn::Manager> impl;
-};
-
-} // namespace Service::Audio

+ 2 - 2
src/core/hle/service/audio/audio.cpp

@@ -2,9 +2,9 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 
 #include "core/core.h"
 #include "core/core.h"
-#include "core/hle/service/audio/audin_u.h"
 #include "core/hle/service/audio/audio.h"
 #include "core/hle/service/audio/audio.h"
 #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/audout_u.h"
 #include "core/hle/service/audio/audout_u.h"
 #include "core/hle/service/audio/audrec_a.h"
 #include "core/hle/service/audio/audrec_a.h"
 #include "core/hle/service/audio/audrec_u.h"
 #include "core/hle/service/audio/audrec_u.h"
@@ -19,8 +19,8 @@ void LoopProcess(Core::System& system) {
     auto server_manager = std::make_unique<ServerManager>(system);
     auto server_manager = std::make_unique<ServerManager>(system);
 
 
     server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
     server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
+    server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system));
     server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
     server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
-    server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system));
     server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
     server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
     server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system));
     server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system));
     server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));
     server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));

+ 126 - 0
src/core/hle/service/audio/audio_in_manager.cpp

@@ -0,0 +1,126 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/string_util.h"
+#include "core/hle/service/audio/audio_in.h"
+#include "core/hle/service/audio/audio_in_manager.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::Audio {
+using namespace AudioCore::AudioIn;
+
+IAudioInManager::IAudioInManager(Core::System& system_)
+    : ServiceFramework{system_, "audin:u"},
+      impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, C<&IAudioInManager::ListAudioIns>, "ListAudioIns"},
+        {1, C<&IAudioInManager::OpenAudioIn>, "OpenAudioIn"},
+        {2, C<&IAudioInManager::ListAudioIns>, "ListAudioInsAuto"},
+        {3, C<&IAudioInManager::OpenAudioIn>, "OpenAudioInAuto"},
+        {4, C<&IAudioInManager::ListAudioInsAutoFiltered>, "ListAudioInsAutoFiltered"},
+        {5, C<&IAudioInManager::OpenAudioInProtocolSpecified>, "OpenAudioInProtocolSpecified"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IAudioInManager::~IAudioInManager() = default;
+
+Result IAudioInManager::ListAudioIns(
+    OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins, Out<u32> out_count) {
+    LOG_DEBUG(Service_Audio, "called");
+    R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
+}
+
+Result IAudioInManager::OpenAudioIn(Out<AudioInParameterInternal> out_parameter_internal,
+                                    Out<SharedPointer<IAudioIn>> out_audio_in,
+                                    OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
+                                    InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
+                                    AudioInParameter parameter,
+                                    InCopyHandle<Kernel::KProcess> process_handle,
+                                    ClientAppletResourceUserId aruid) {
+    LOG_DEBUG(Service_Audio, "called");
+    R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
+                                                name, {}, parameter, process_handle, aruid));
+}
+
+Result IAudioInManager::ListAudioInsAuto(
+    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
+    LOG_DEBUG(Service_Audio, "called");
+    R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
+}
+
+Result IAudioInManager::OpenAudioInAuto(
+    Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
+    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+    InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioInParameter parameter,
+    InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
+    LOG_DEBUG(Service_Audio, "called");
+    R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
+                                                name, {}, parameter, process_handle, aruid));
+}
+
+Result IAudioInManager::ListAudioInsAutoFiltered(
+    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
+    LOG_DEBUG(Service_Audio, "called");
+    *out_count = impl->GetDeviceNames(out_audio_ins, true);
+    R_SUCCEED();
+}
+
+Result IAudioInManager::OpenAudioInProtocolSpecified(
+    Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
+    OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+    InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
+    AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
+    ClientAppletResourceUserId aruid) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    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);
+    }
+
+    std::scoped_lock l{impl->mutex};
+
+    size_t new_session_id{};
+
+    R_TRY(impl->LinkToManager());
+    R_TRY(impl->AcquireSessionId(new_session_id));
+
+    LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
+              impl->num_free_sessions);
+
+    const auto name_buffer = std::span(reinterpret_cast<const u8*>(name[0].name.data()), 0x100);
+    const auto device_name = Common::StringFromBuffer(name_buffer);
+    *out_audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
+                                               parameter, process_handle.Get(), aruid.pid);
+    impl->sessions[new_session_id] = (*out_audio_in)->GetImpl();
+    impl->applet_resource_user_ids[new_session_id] = aruid.pid;
+
+    auto& out_system = impl->sessions[new_session_id]->GetSystem();
+    *out_parameter_internal =
+        AudioInParameterInternal{.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())};
+
+    out_name[0] = AudioDeviceName(out_system.GetName());
+
+    if (protocol == Protocol{}) {
+        if (out_system.IsUac()) {
+            out_name[0] = AudioDeviceName("UacIn");
+        } else {
+            out_name[0] = AudioDeviceName("DeviceIn");
+        }
+    }
+
+    R_SUCCEED();
+}
+
+} // namespace Service::Audio

+ 57 - 0
src/core/hle/service/audio/audio_in_manager.h

@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/audio_in_manager.h"
+#include "audio_core/in/audio_in_system.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
+using Protocol = std::array<u32, 2>;
+
+class IAudioIn;
+
+class IAudioInManager final : public ServiceFramework<IAudioInManager> {
+public:
+    explicit IAudioInManager(Core::System& system_);
+    ~IAudioInManager() override;
+
+private:
+    Result ListAudioIns(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins,
+                        Out<u32> out_count);
+    Result OpenAudioIn(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
+                       Out<SharedPointer<IAudioIn>> out_audio_in,
+                       OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
+                       InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
+                       AudioCore::AudioIn::AudioInParameter parameter,
+                       InCopyHandle<Kernel::KProcess> process_handle,
+                       ClientAppletResourceUserId aruid);
+
+    Result ListAudioInsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins,
+                            Out<u32> out_count);
+    Result OpenAudioInAuto(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
+                           Out<SharedPointer<IAudioIn>> out_audio_in,
+                           OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+                           InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
+                           AudioCore::AudioIn::AudioInParameter parameter,
+                           InCopyHandle<Kernel::KProcess> process_handle,
+                           ClientAppletResourceUserId aruid);
+
+    Result ListAudioInsAutoFiltered(
+        OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count);
+    Result OpenAudioInProtocolSpecified(
+        Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
+        Out<SharedPointer<IAudioIn>> out_audio_in,
+        OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+        InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
+        AudioCore::AudioIn::AudioInParameter parameter,
+        InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);
+
+    std::unique_ptr<AudioCore::AudioIn::Manager> impl;
+};
+
+} // namespace Service::Audio