Implement IAudioDevice for accessing audio output properties

This is used by Super Mario Odyssey in its init routine.
This commit is contained in:
Billy Laws 2020-07-09 14:48:14 +01:00 committed by ◱ PixelyIon
parent f71b54b901
commit 6548d4914d
6 changed files with 110 additions and 1 deletions

View File

@ -60,6 +60,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/services/fatalsrv/IService.cpp
${source_DIR}/skyline/services/audio/IAudioOutManager.cpp
${source_DIR}/skyline/services/audio/IAudioOut.cpp
${source_DIR}/skyline/services/audio/IAudioDevice.cpp
${source_DIR}/skyline/services/audio/IAudioRendererManager.cpp
${source_DIR}/skyline/services/audio/IAudioRenderer/IAudioRenderer.cpp
${source_DIR}/skyline/services/audio/IAudioRenderer/voice.cpp

View File

@ -0,0 +1,51 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <kernel/types/KProcess.h>
#include <audio/common.h>
#include "IAudioDevice.h"
namespace skyline::service::audio {
IAudioDevice::IAudioDevice(const DeviceState &state, ServiceManager &manager) : systemEvent(std::make_shared<type::KEvent>(state)), BaseService(state, manager, Service::audio_IAudioDevice, "audio:IAudioDevice", {
{0x0, SFUNC(IAudioDevice::ListAudioDeviceName)},
{0x1, SFUNC(IAudioDevice::SetAudioDeviceOutputVolume)},
{0x3, SFUNC(IAudioDevice::GetActiveAudioDeviceName)},
{0x4, SFUNC(IAudioDevice::QueryAudioDeviceSystemEvent)},
{0x5, SFUNC(IAudioDevice::GetActiveChannelCount)},
{0x6, SFUNC(IAudioDevice::ListAudioDeviceName)},
{0x7, SFUNC(IAudioDevice::SetAudioDeviceOutputVolume)},
{0xa, SFUNC(IAudioDevice::GetActiveAudioDeviceName)}
}) {}
void IAudioDevice::ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
u64 offset{};
for (std::string deviceName : {"AudioTvOutput", "AudioStereoJackOutput", "AudioBuiltInSpeakerOutput"}) {
if (offset + deviceName.size() + 1 > request.outputBuf.at(0).size)
throw exception("Too small a buffer supplied to ListAudioDeviceName");
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address + offset, deviceName.size() + 1);
offset += deviceName.size() + 1;
}
}
void IAudioDevice::SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void IAudioDevice::GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
std::string deviceName("AudioStereoJackOutput");
if (deviceName.size() > request.outputBuf.at(0).size)
throw exception("Too small a buffer supplied to GetActiveAudioDeviceName");
state.process->WriteMemory(deviceName.c_str(), request.outputBuf.at(0).address, deviceName.size() + 1);
}
void IAudioDevice::QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto handle = state.process->InsertItem(systemEvent);
state.logger->Debug("Audio Device System Event Handle: 0x{:X}", handle);
response.copyHandles.push_back(handle);
}
void IAudioDevice::GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.Push<u32>(constant::ChannelCount);
}
}

View File

@ -0,0 +1,45 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <services/base_service.h>
#include <services/serviceman.h>
namespace skyline::service::audio {
/**
* @brief IAudioDevice is used by applications to query audio device info (https://switchbrew.org/wiki/Audio_services#IAudioDevice)
*/
class IAudioDevice : public BaseService {
private:
std::shared_ptr<type::KEvent> systemEvent; //!< The KEvent that is signalled on audio device changes
public:
IAudioDevice(const DeviceState &state, ServiceManager &manager);
/**
* @brief This returns a list of the available audio devices (https://switchbrew.org/wiki/Audio_services#ListAudioDeviceName)
*/
void ListAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This sets the volume of an audio output (https://switchbrew.org/wiki/Audio_services#SetAudioDeviceOutputVolume)
*/
void SetAudioDeviceOutputVolume(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns the active audio output device
*/
void GetActiveAudioDeviceName(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns the audio device system event
*/
void QueryAudioDeviceSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns the current output devices channel count
*/
void GetActiveChannelCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}

View File

@ -3,12 +3,14 @@
#include <kernel/types/KProcess.h>
#include "IAudioRenderer/IAudioRenderer.h"
#include "IAudioDevice.h"
#include "IAudioRendererManager.h"
namespace skyline::service::audio {
IAudioRendererManager::IAudioRendererManager(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::audio_IAudioRendererManager, "audio:IAudioRendererManager", {
{0x0, SFUNC(IAudioRendererManager::OpenAudioRenderer)},
{0x1, SFUNC(IAudioRendererManager::GetAudioRendererWorkBufferSize)}
{0x1, SFUNC(IAudioRendererManager::GetAudioRendererWorkBufferSize)},
{0x2, SFUNC(IAudioRendererManager::GetAudioDeviceService)}
}) {}
void IAudioRendererManager::OpenAudioRenderer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
@ -84,4 +86,8 @@ namespace skyline::service::audio {
state.logger->Debug("IAudioRendererManager: Work buffer size: 0x{:X}", size);
response.Push<i64>(size);
}
void IAudioRendererManager::GetAudioDeviceService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.RegisterService(SRVREG(IAudioDevice), session, response);
}
}

View File

@ -23,5 +23,10 @@ namespace skyline::service::audio {
* @brief Calculates the size of the buffer the guest needs to allocate for IAudioRendererManager
*/
void GetAudioRendererWorkBufferSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns a handle to an instance of an IAudioDevice (https://switchbrew.org/wiki/Audio_services#GetAudioDeviceService)
*/
void GetAudioDeviceService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}

View File

@ -49,6 +49,7 @@ namespace skyline::service {
audio_IAudioOut,
audio_IAudioRendererManager,
audio_IAudioRenderer,
audio_IAudioDevice,
hid_IHidServer,
hid_IAppletResource,
timesrv_IStaticService,