js8call/NotificationAudio.cpp
Allan Bazinet 210dea5183 Simpler memory management in NotificationAudio
QByteArray is an implicitly-shared COW class, and we never change it after we read it into cache, so memory managment can be simpler here. Removed unused decoder instance variable, and moved use of file instance variable to automatic local scope. Converted from QMap to QCache, as order of cached entries is irrelevant to us.
2024-09-16 08:42:58 -07:00

85 lines
2 KiB
C++

#include "NotificationAudio.h"
#include <QDebug>
#include "Audio/BWFFile.hpp"
#include "soundout.h"
NotificationAudio::NotificationAudio(QObject * parent)
: QObject {parent}
, m_stream {new SoundOutput}
{
connect(m_stream.data(), &SoundOutput::status, this, &NotificationAudio::status);
connect(m_stream.data(), &SoundOutput::error, this, &NotificationAudio::error);
}
NotificationAudio::~NotificationAudio()
{
stop();
}
void NotificationAudio::status(QString const message)
{
if (message == "Idle") stop();
}
void NotificationAudio::error(QString const message)
{
qDebug() << "notification error:" << message;
}
void
NotificationAudio::setDevice(QAudioDevice const & device,
unsigned const msBuffer)
{
m_device = device;
m_msBuffer = msBuffer;
m_stream->setFormat(device, 2, msBuffer);
}
void
NotificationAudio::play(QString const & filePath)
{
auto const playEntry = [this, &filePath](auto const it)
{
auto const & [format, data] = *it;
if (m_buffer.isOpen()) m_buffer.close();
m_buffer.setData(data);
if (m_buffer.open(QIODevice::ReadOnly))
{
qDebug() << "notification: playing" << filePath << "with format" << format;
m_stream->setDeviceFormat(m_device, format, m_msBuffer);
m_stream->restart(&m_buffer);
}
};
if (auto const it = m_cache.constFind(filePath);
it != m_cache.constEnd())
{
qDebug() << "notifcation: cache hit on" << filePath;
playEntry(it);
}
else
{
qDebug() << "notifcation: cache miss on" << filePath;
if (auto file = BWFFile(QAudioFormat{}, filePath);
file.open(QIODevice::ReadOnly))
{
if (auto data = file.readAll();
!data.isEmpty())
{
playEntry(m_cache.emplace(filePath, file.format(), data));
}
}
}
}
void
NotificationAudio::stop()
{
m_stream->stop();
}