audio_in.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "core/hle/service/audio/audio_in.h"
  4. #include "core/hle/service/cmif_serialization.h"
  5. #include "core/hle/service/ipc_helpers.h"
  6. namespace Service::Audio {
  7. using namespace AudioCore::AudioIn;
  8. IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
  9. const std::string& device_name, const AudioInParameter& in_params,
  10. Kernel::KProcess* handle, u64 applet_resource_user_id)
  11. : ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
  12. event{service_context.CreateEvent("AudioInEvent")},
  13. impl{std::make_shared<In>(system_, manager, event, session_id)} {
  14. // clang-format off
  15. static const FunctionInfo functions[] = {
  16. {0, D<&IAudioIn::GetAudioInState>, "GetAudioInState"},
  17. {1, D<&IAudioIn::Start>, "Start"},
  18. {2, D<&IAudioIn::Stop>, "Stop"},
  19. {3, D<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"},
  20. {4, D<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"},
  21. {5, D<&IAudioIn::GetReleasedAudioInBuffers>, "GetReleasedAudioInBuffers"},
  22. {6, D<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"},
  23. {7, D<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"},
  24. {8, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendAudioInBufferAuto"},
  25. {9, D<&IAudioIn::GetReleasedAudioInBuffersAuto>, "GetReleasedAudioInBuffersAuto"},
  26. {10, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendUacInBufferAuto"},
  27. {11, D<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"},
  28. {12, D<&IAudioIn::SetDeviceGain>, "SetDeviceGain"},
  29. {13, D<&IAudioIn::GetDeviceGain>, "GetDeviceGain"},
  30. {14, D<&IAudioIn::FlushAudioInBuffers>, "FlushAudioInBuffers"},
  31. };
  32. // clang-format on
  33. RegisterHandlers(functions);
  34. process->Open();
  35. if (impl->GetSystem()
  36. .Initialize(device_name, in_params, handle, applet_resource_user_id)
  37. .IsError()) {
  38. LOG_ERROR(Service_Audio, "Failed to initialize the AudioIn System!");
  39. }
  40. }
  41. IAudioIn::~IAudioIn() {
  42. impl->Free();
  43. service_context.CloseEvent(event);
  44. process->Close();
  45. }
  46. Result IAudioIn::GetAudioInState(Out<u32> out_state) {
  47. *out_state = static_cast<u32>(impl->GetState());
  48. LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
  49. R_SUCCEED();
  50. }
  51. Result IAudioIn::Start() {
  52. LOG_DEBUG(Service_Audio, "called");
  53. R_RETURN(impl->StartSystem());
  54. }
  55. Result IAudioIn::Stop() {
  56. LOG_DEBUG(Service_Audio, "called");
  57. R_RETURN(impl->StopSystem());
  58. }
  59. Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
  60. u64 buffer_client_ptr) {
  61. R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr));
  62. }
  63. Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
  64. u64 buffer_client_ptr) {
  65. if (buffer.empty()) {
  66. LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
  67. R_THROW(Audio::ResultInsufficientBuffer);
  68. }
  69. [[maybe_unused]] const auto session_id{impl->GetSystem().GetSessionId()};
  70. LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", session_id,
  71. buffer_client_ptr);
  72. R_RETURN(impl->AppendBuffer(buffer[0], buffer_client_ptr));
  73. }
  74. Result IAudioIn::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
  75. LOG_DEBUG(Service_Audio, "called");
  76. *out_event = &impl->GetBufferEvent();
  77. R_SUCCEED();
  78. }
  79. Result IAudioIn::GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
  80. Out<u32> out_count) {
  81. R_RETURN(this->GetReleasedAudioInBuffersAuto(out_audio_buffer, out_count));
  82. }
  83. Result IAudioIn::GetReleasedAudioInBuffersAuto(
  84. OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {
  85. if (!out_audio_buffer.empty()) {
  86. out_audio_buffer[0] = 0;
  87. }
  88. *out_count = impl->GetReleasedBuffers(out_audio_buffer);
  89. LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
  90. impl->GetSystem().GetSessionId(), *out_count);
  91. R_SUCCEED();
  92. }
  93. Result IAudioIn::ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
  94. *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);
  95. LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
  96. *out_contains_buffer);
  97. R_SUCCEED();
  98. }
  99. Result IAudioIn::GetAudioInBufferCount(Out<u32> out_buffer_count) {
  100. *out_buffer_count = impl->GetBufferCount();
  101. LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
  102. R_SUCCEED();
  103. }
  104. Result IAudioIn::SetDeviceGain(f32 device_gain) {
  105. impl->SetVolume(device_gain);
  106. LOG_DEBUG(Service_Audio, "called. Gain {}", device_gain);
  107. R_SUCCEED();
  108. }
  109. Result IAudioIn::GetDeviceGain(Out<f32> out_device_gain) {
  110. *out_device_gain = impl->GetVolume();
  111. LOG_DEBUG(Service_Audio, "called. Gain {}", *out_device_gain);
  112. R_SUCCEED();
  113. }
  114. Result IAudioIn::FlushAudioInBuffers(Out<bool> out_flushed) {
  115. *out_flushed = impl->FlushAudioInBuffers();
  116. LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
  117. R_SUCCEED();
  118. }
  119. } // namespace Service::Audio