mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:57:45 +00:00
Ladybird: Move Qt-specific classes and functions to a Qt subdirectory
This will help a lot with developing chromes for different UI frameworks where we can see which helper classes and processes are really using Qt vs just using it to get at helper data. As a bonus, remove Qt dependency from WebDriver.
This commit is contained in:
parent
ccaa423372
commit
391beef707
53 changed files with 160 additions and 157 deletions
103
Ladybird/Qt/AudioThread.h
Normal file
103
Ladybird/Qt/AudioThread.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Endian.h>
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/Types.h>
|
||||
#include <LibAudio/Loader.h>
|
||||
#include <LibAudio/Sample.h>
|
||||
#include <LibCore/SharedCircularQueue.h>
|
||||
#include <QAudioFormat>
|
||||
#include <QAudioSink>
|
||||
#include <QByteArray>
|
||||
#include <QMediaDevices>
|
||||
#include <QThread>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
static constexpr u32 UPDATE_RATE_MS = 10;
|
||||
|
||||
struct AudioTask {
|
||||
enum class Type {
|
||||
Stop,
|
||||
Play,
|
||||
Pause,
|
||||
Seek,
|
||||
Volume,
|
||||
RecreateAudioDevice,
|
||||
};
|
||||
|
||||
Type type;
|
||||
Optional<double> data {};
|
||||
};
|
||||
|
||||
using AudioTaskQueue = Core::SharedSingleProducerCircularQueue<AudioTask>;
|
||||
|
||||
class AudioThread final : public QThread { // We have to use QThread, otherwise internal Qt media QTimer objects do not work.
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullOwnPtr<AudioThread>> create(NonnullRefPtr<Audio::Loader> loader);
|
||||
|
||||
ErrorOr<void> stop();
|
||||
|
||||
Duration duration() const { return m_duration; }
|
||||
|
||||
ErrorOr<void> queue_task(AudioTask task);
|
||||
|
||||
Q_SIGNALS:
|
||||
void playback_position_updated(Duration);
|
||||
|
||||
private:
|
||||
AudioThread(NonnullRefPtr<Audio::Loader> loader, AudioTaskQueue task_queue);
|
||||
|
||||
enum class Paused {
|
||||
Yes,
|
||||
No,
|
||||
};
|
||||
|
||||
void run() override;
|
||||
|
||||
ErrorOr<Paused> play_next_samples(QAudioSink& audio_output, QIODevice& io_device);
|
||||
|
||||
void enqueue_samples(QAudioSink const& audio_output, QIODevice& io_device, FixedArray<Audio::Sample> samples);
|
||||
|
||||
template<typename T>
|
||||
void write_sample(FixedMemoryStream& stream, float sample)
|
||||
{
|
||||
// The values that need to be written to the stream vary depending on the output channel format, and isn't
|
||||
// particularly well documented. The value derivations performed below were adapted from a Qt example:
|
||||
// https://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/audiooutput/audiooutput.cpp?h=6.4.2#n46
|
||||
LittleEndian<T> pcm;
|
||||
|
||||
if constexpr (IsSame<T, u8>)
|
||||
pcm = static_cast<u8>((sample + 1.0f) / 2 * NumericLimits<u8>::max());
|
||||
else if constexpr (IsSame<T, i16>)
|
||||
pcm = static_cast<i16>(sample * NumericLimits<i16>::max());
|
||||
else if constexpr (IsSame<T, i32>)
|
||||
pcm = static_cast<i32>(sample * NumericLimits<i32>::max());
|
||||
else if constexpr (IsSame<T, float>)
|
||||
pcm = sample;
|
||||
else
|
||||
static_assert(DependentFalse<T>);
|
||||
|
||||
MUST(stream.write_value(pcm));
|
||||
}
|
||||
|
||||
NonnullRefPtr<Audio::Loader> m_loader;
|
||||
AudioTaskQueue m_task_queue;
|
||||
|
||||
QByteArray m_sample_buffer;
|
||||
|
||||
Duration m_duration;
|
||||
Duration m_position;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue