mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 16:55:09 +00:00
Ladybird+LibWeb+WebContent: Create a platform plugin for playing audio
This creates (and installs upon WebContent startup) a platform plugin to play audio data. On Serenity, we use AudioServer to play audio over IPC. Unfortunately, AudioServer is currently coupled with Serenity's audio devices, and thus cannot be used in Ladybird on Lagom. Instead, we use a Qt audio device to play the audio, which requires the Qt multimedia package. While we use Qt to play the audio, note that we can still use LibAudio to decode the audio data and retrieve samples - we simply send Qt the raw PCM signals.
This commit is contained in:
parent
ee48d7514f
commit
a34e369252
15 changed files with 317 additions and 9 deletions
89
Ladybird/AudioCodecPluginLadybird.cpp
Normal file
89
Ladybird/AudioCodecPluginLadybird.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "AudioCodecPluginLadybird.h"
|
||||
#include <AK/Endian.h>
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <LibAudio/Sample.h>
|
||||
#include <QAudioFormat>
|
||||
#include <QAudioSink>
|
||||
#include <QBuffer>
|
||||
#include <QMediaDevices>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
ErrorOr<NonnullOwnPtr<AudioCodecPluginLadybird>> AudioCodecPluginLadybird::create()
|
||||
{
|
||||
auto devices = TRY(adopt_nonnull_own_or_enomem(new (nothrow) QMediaDevices()));
|
||||
auto const& device_info = devices->defaultAudioOutput();
|
||||
|
||||
auto format = device_info.preferredFormat();
|
||||
format.setSampleFormat(QAudioFormat::Int16);
|
||||
format.setChannelCount(2);
|
||||
|
||||
if (!device_info.isFormatSupported(format))
|
||||
return Error::from_string_literal("Audio device format not supported");
|
||||
|
||||
auto audio_output = TRY(adopt_nonnull_own_or_enomem(new (nothrow) QAudioSink(device_info, format)));
|
||||
|
||||
return adopt_nonnull_own_or_enomem(new (nothrow) AudioCodecPluginLadybird(move(devices), move(audio_output)));
|
||||
}
|
||||
|
||||
AudioCodecPluginLadybird::AudioCodecPluginLadybird(NonnullOwnPtr<QMediaDevices> devices, NonnullOwnPtr<QAudioSink> audio_output)
|
||||
: m_devices(move(devices))
|
||||
, m_audio_output(move(audio_output))
|
||||
, m_io_device(m_audio_output->start())
|
||||
{
|
||||
}
|
||||
|
||||
AudioCodecPluginLadybird::~AudioCodecPluginLadybird() = default;
|
||||
|
||||
size_t AudioCodecPluginLadybird::device_sample_rate()
|
||||
{
|
||||
return m_audio_output->format().sampleRate();
|
||||
}
|
||||
|
||||
void AudioCodecPluginLadybird::enqueue_samples(FixedArray<Audio::Sample> samples)
|
||||
{
|
||||
QByteArray buffer;
|
||||
buffer.resize(samples.size() * 2 * sizeof(u16));
|
||||
|
||||
FixedMemoryStream stream { Bytes { buffer.data(), static_cast<size_t>(buffer.size()) } };
|
||||
|
||||
for (auto& sample : samples) {
|
||||
LittleEndian<i16> pcm;
|
||||
|
||||
pcm = static_cast<i16>(sample.left * NumericLimits<i16>::max());
|
||||
MUST(stream.write_value(pcm));
|
||||
|
||||
pcm = static_cast<i16>(sample.right * NumericLimits<i16>::max());
|
||||
MUST(stream.write_value(pcm));
|
||||
}
|
||||
|
||||
m_io_device->write(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
size_t AudioCodecPluginLadybird::remaining_samples() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioCodecPluginLadybird::resume_playback()
|
||||
{
|
||||
m_audio_output->resume();
|
||||
}
|
||||
|
||||
void AudioCodecPluginLadybird::pause_playback()
|
||||
{
|
||||
m_audio_output->suspend();
|
||||
}
|
||||
|
||||
void AudioCodecPluginLadybird::playback_ended()
|
||||
{
|
||||
m_audio_output->suspend();
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue