mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 01:17:35 +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
59
Userland/Services/WebContent/AudioCodecPluginSerenity.cpp
Normal file
59
Userland/Services/WebContent/AudioCodecPluginSerenity.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibAudio/ConnectionToServer.h>
|
||||
#include <WebContent/AudioCodecPluginSerenity.h>
|
||||
|
||||
namespace WebContent {
|
||||
|
||||
ErrorOr<NonnullOwnPtr<AudioCodecPluginSerenity>> AudioCodecPluginSerenity::create()
|
||||
{
|
||||
auto connection = TRY(Audio::ConnectionToServer::try_create());
|
||||
return adopt_nonnull_own_or_enomem(new (nothrow) AudioCodecPluginSerenity(move(connection)));
|
||||
}
|
||||
|
||||
AudioCodecPluginSerenity::AudioCodecPluginSerenity(NonnullRefPtr<Audio::ConnectionToServer> connection)
|
||||
: m_connection(move(connection))
|
||||
{
|
||||
}
|
||||
|
||||
AudioCodecPluginSerenity::~AudioCodecPluginSerenity() = default;
|
||||
|
||||
size_t AudioCodecPluginSerenity::device_sample_rate()
|
||||
{
|
||||
if (!m_device_sample_rate.has_value())
|
||||
m_device_sample_rate = m_connection->get_sample_rate();
|
||||
return *m_device_sample_rate;
|
||||
}
|
||||
|
||||
void AudioCodecPluginSerenity::enqueue_samples(FixedArray<Audio::Sample> samples)
|
||||
{
|
||||
m_connection->async_enqueue(move(samples)).release_value_but_fixme_should_propagate_errors();
|
||||
}
|
||||
|
||||
size_t AudioCodecPluginSerenity::remaining_samples() const
|
||||
{
|
||||
return m_connection->remaining_samples();
|
||||
}
|
||||
|
||||
void AudioCodecPluginSerenity::resume_playback()
|
||||
{
|
||||
m_connection->async_start_playback();
|
||||
}
|
||||
|
||||
void AudioCodecPluginSerenity::pause_playback()
|
||||
{
|
||||
m_connection->async_start_playback();
|
||||
}
|
||||
|
||||
void AudioCodecPluginSerenity::playback_ended()
|
||||
{
|
||||
m_connection->async_pause_playback();
|
||||
m_connection->clear_client_buffer();
|
||||
m_connection->async_clear_buffer();
|
||||
}
|
||||
|
||||
}
|
38
Userland/Services/WebContent/AudioCodecPluginSerenity.h
Normal file
38
Userland/Services/WebContent/AudioCodecPluginSerenity.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <LibAudio/Forward.h>
|
||||
#include <LibWeb/Platform/AudioCodecPlugin.h>
|
||||
|
||||
namespace WebContent {
|
||||
|
||||
class AudioCodecPluginSerenity final : public Web::Platform::AudioCodecPlugin {
|
||||
public:
|
||||
static ErrorOr<NonnullOwnPtr<AudioCodecPluginSerenity>> create();
|
||||
virtual ~AudioCodecPluginSerenity() override;
|
||||
|
||||
virtual size_t device_sample_rate() override;
|
||||
|
||||
virtual void enqueue_samples(FixedArray<Audio::Sample>) override;
|
||||
virtual size_t remaining_samples() const override;
|
||||
|
||||
virtual void resume_playback() override;
|
||||
virtual void pause_playback() override;
|
||||
virtual void playback_ended() override;
|
||||
|
||||
private:
|
||||
explicit AudioCodecPluginSerenity(NonnullRefPtr<Audio::ConnectionToServer>);
|
||||
|
||||
NonnullRefPtr<Audio::ConnectionToServer> m_connection;
|
||||
Optional<size_t> m_device_sample_rate;
|
||||
};
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@ compile_ipc(WebDriverClient.ipc WebDriverClientEndpoint.h)
|
|||
compile_ipc(WebDriverServer.ipc WebDriverServerEndpoint.h)
|
||||
|
||||
set(SOURCES
|
||||
AudioCodecPluginSerenity.cpp
|
||||
ConnectionFromClient.cpp
|
||||
ConsoleGlobalEnvironmentExtensions.cpp
|
||||
ImageCodecPluginSerenity.cpp
|
||||
|
@ -28,5 +29,5 @@ set(GENERATED_SOURCES
|
|||
)
|
||||
|
||||
serenity_bin(WebContent)
|
||||
target_link_libraries(WebContent PRIVATE LibCore LibFileSystem LibIPC LibGfx LibImageDecoderClient LibJS LibWebView LibWeb LibLocale LibMain)
|
||||
target_link_libraries(WebContent PRIVATE LibCore LibFileSystem LibIPC LibGfx LibAudio LibImageDecoderClient LibJS LibWebView LibWeb LibLocale LibMain)
|
||||
link_with_locale_data(WebContent)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "AudioCodecPluginSerenity.h"
|
||||
#include "ImageCodecPluginSerenity.h"
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/LocalServer.h>
|
||||
|
@ -25,7 +26,7 @@
|
|||
ErrorOr<int> serenity_main(Main::Arguments)
|
||||
{
|
||||
Core::EventLoop event_loop;
|
||||
TRY(Core::System::pledge("stdio recvfd sendfd accept unix rpath thread"));
|
||||
TRY(Core::System::pledge("stdio recvfd sendfd accept unix rpath thread proc"));
|
||||
|
||||
// This must be first; we can't check if /tmp/webdriver exists once we've unveiled other paths.
|
||||
auto webdriver_socket_path = DeprecatedString::formatted("{}/webdriver", TRY(Core::StandardPaths::runtime_directory()));
|
||||
|
@ -35,6 +36,7 @@ ErrorOr<int> serenity_main(Main::Arguments)
|
|||
TRY(Core::System::unveil("/res", "r"));
|
||||
TRY(Core::System::unveil("/etc/timezone", "r"));
|
||||
TRY(Core::System::unveil("/usr/lib", "r"));
|
||||
TRY(Core::System::unveil("/tmp/session/%sid/portal/audio", "rw"));
|
||||
TRY(Core::System::unveil("/tmp/session/%sid/portal/request", "rw"));
|
||||
TRY(Core::System::unveil("/tmp/session/%sid/portal/image", "rw"));
|
||||
TRY(Core::System::unveil("/tmp/session/%sid/portal/websocket", "rw"));
|
||||
|
@ -44,6 +46,10 @@ ErrorOr<int> serenity_main(Main::Arguments)
|
|||
Web::Platform::ImageCodecPlugin::install(*new WebContent::ImageCodecPluginSerenity);
|
||||
Web::Platform::FontPlugin::install(*new Web::Platform::FontPluginSerenity);
|
||||
|
||||
Web::Platform::AudioCodecPlugin::install_creation_hook([] {
|
||||
return WebContent::AudioCodecPluginSerenity::create();
|
||||
});
|
||||
|
||||
Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create()));
|
||||
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create()));
|
||||
TRY(Web::Bindings::initialize_main_thread_vm());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue