minetest/src/client/sound/proxy_sound_manager.cpp

168 lines
4.2 KiB
C++

/*
Minetest
Copyright (C) 2023 DS
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "proxy_sound_manager.h"
#include "filesys.h"
namespace sound {
ProxySoundManager::MsgResult ProxySoundManager::handleMsg(SoundManagerMsgToProxy &&msg)
{
using namespace sound_manager_messages_to_proxy;
return std::visit([&](auto &&msg) {
using T = std::decay_t<decltype(msg)>;
if constexpr (std::is_same_v<T, std::monostate>)
return MsgResult::Empty;
else if constexpr (std::is_same_v<T, ReportRemovedSound>)
reportRemovedSound(msg.id);
else if constexpr (std::is_same_v<T, Stopped>)
return MsgResult::Stopped;
return MsgResult::Ok;
},
std::move(msg));
}
ProxySoundManager::~ProxySoundManager()
{
if (m_sound_manager.isRunning()) {
send(sound_manager_messages_to_mgr::PleaseStop{});
// recv until it stopped
auto recv = [&] {
return m_sound_manager.m_queue_to_proxy.pop_frontNoEx();
};
while (true) {
if (handleMsg(recv()) == MsgResult::Stopped)
break;
}
// join
m_sound_manager.stop();
SANITY_CHECK(m_sound_manager.wait());
}
}
void ProxySoundManager::step(f32 dtime)
{
auto recv = [&] {
return m_sound_manager.m_queue_to_proxy.pop_frontNoEx(0);
};
while (true) {
MsgResult res = handleMsg(recv());
if (res == MsgResult::Empty)
break;
else if (res == MsgResult::Stopped)
throw std::runtime_error("OpenALSoundManager stopped unexpectedly");
}
}
void ProxySoundManager::pauseAll()
{
send(sound_manager_messages_to_mgr::PauseAll{});
}
void ProxySoundManager::resumeAll()
{
send(sound_manager_messages_to_mgr::ResumeAll{});
}
void ProxySoundManager::updateListener(const v3f &pos_, const v3f &vel_,
const v3f &at_, const v3f &up_)
{
send(sound_manager_messages_to_mgr::UpdateListener{pos_, vel_, at_, up_});
}
void ProxySoundManager::setListenerGain(f32 gain)
{
send(sound_manager_messages_to_mgr::SetListenerGain{gain});
}
bool ProxySoundManager::loadSoundFile(const std::string &name,
const std::string &filepath)
{
// do not add twice
if (m_known_sound_names.count(name) != 0)
return false;
// coarse check
if (!fs::IsFile(filepath))
return false;
send(sound_manager_messages_to_mgr::LoadSoundFile{name, filepath});
m_known_sound_names.insert(name);
return true;
}
bool ProxySoundManager::loadSoundData(const std::string &name, std::string &&filedata)
{
// do not add twice
if (m_known_sound_names.count(name) != 0)
return false;
send(sound_manager_messages_to_mgr::LoadSoundData{name, std::move(filedata)});
m_known_sound_names.insert(name);
return true;
}
void ProxySoundManager::addSoundToGroup(const std::string &sound_name,
const std::string &group_name)
{
send(sound_manager_messages_to_mgr::AddSoundToGroup{sound_name, group_name});
}
void ProxySoundManager::playSound(sound_handle_t id, const SoundSpec &spec)
{
if (id == 0)
id = allocateId(1);
send(sound_manager_messages_to_mgr::PlaySound{id, spec});
}
void ProxySoundManager::playSoundAt(sound_handle_t id, const SoundSpec &spec, const v3f &pos_,
const v3f &vel_)
{
if (id == 0)
id = allocateId(1);
send(sound_manager_messages_to_mgr::PlaySoundAt{id, spec, pos_, vel_});
}
void ProxySoundManager::stopSound(sound_handle_t sound)
{
send(sound_manager_messages_to_mgr::StopSound{sound});
}
void ProxySoundManager::fadeSound(sound_handle_t soundid, f32 step, f32 target_gain)
{
send(sound_manager_messages_to_mgr::FadeSound{soundid, step, target_gain});
}
void ProxySoundManager::updateSoundPosVel(sound_handle_t sound, const v3f &pos_, const v3f &vel_)
{
send(sound_manager_messages_to_mgr::UpdateSoundPosVel{sound, pos_, vel_});
}
} // namespace sound