mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 03:55:24 +00:00
AudioServer: Begin work on a new IPC API style.
The goal here is to generate most of this code from IPC protocol descriptions, but for now I've spelled them all out to get started. Each message gets a wrapper class in the ASAPI_Client or ASAPI_Server namespace. They are convertible to and from the old message structs. The real hotness happens when you want to make a synchronous request to the other side: auto response = send_sync<ASAPI_Client::GetMainMixVolume>(); Each request class knows his corresponding response class, so in the above example, "response" will be an ASAPI_Server::DidGetMainMixVolume object, and we can get the volume like so: int volume = response.volume(); For posting messages that don't expect a response, you can still use post_message() since the message classes are convertible: post_message(ASAPI_Server::DidGetMainMixVolume(volume)); It's not perfect yet, but I already really like it. :^)
This commit is contained in:
parent
a175e76948
commit
e6db1b81b8
Notes:
sideshowbarker
2024-07-19 12:59:36 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/e6db1b81b80
4 changed files with 227 additions and 40 deletions
|
@ -9,23 +9,17 @@ AClientConnection::AClientConnection()
|
|||
|
||||
void AClientConnection::handshake()
|
||||
{
|
||||
ASAPI_ClientMessage request;
|
||||
request.type = ASAPI_ClientMessage::Type::Greeting;
|
||||
request.greeting.client_pid = getpid();
|
||||
auto response = sync_request(request, ASAPI_ServerMessage::Type::Greeting);
|
||||
set_server_pid(response.greeting.server_pid);
|
||||
set_my_client_id(response.greeting.your_client_id);
|
||||
auto response = send_sync<ASAPI_Client::Greeting>(getpid());
|
||||
set_server_pid(response.server_pid());
|
||||
set_my_client_id(response.your_client_id());
|
||||
}
|
||||
|
||||
void AClientConnection::enqueue(const ABuffer& buffer)
|
||||
{
|
||||
for (;;) {
|
||||
const_cast<ABuffer&>(buffer).shared_buffer().share_with(server_pid());
|
||||
ASAPI_ClientMessage request;
|
||||
request.type = ASAPI_ClientMessage::Type::EnqueueBuffer;
|
||||
request.play_buffer.buffer_id = buffer.shared_buffer_id();
|
||||
auto response = sync_request(request, ASAPI_ServerMessage::Type::EnqueueBufferResponse);
|
||||
if (response.success)
|
||||
auto response = send_sync<ASAPI_Client::EnqueueBuffer>(buffer.shared_buffer_id());
|
||||
if (response.success())
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
|
@ -33,16 +27,10 @@ void AClientConnection::enqueue(const ABuffer& buffer)
|
|||
|
||||
int AClientConnection::get_main_mix_volume()
|
||||
{
|
||||
ASAPI_ClientMessage request;
|
||||
request.type = ASAPI_ClientMessage::Type::GetMainMixVolume;
|
||||
auto response = sync_request(request, ASAPI_ServerMessage::Type::DidGetMainMixVolume);
|
||||
return response.value;
|
||||
return send_sync<ASAPI_Client::GetMainMixVolume>().volume();
|
||||
}
|
||||
|
||||
void AClientConnection::set_main_mix_volume(int volume)
|
||||
{
|
||||
ASAPI_ClientMessage request;
|
||||
request.type = ASAPI_ClientMessage::Type::SetMainMixVolume;
|
||||
request.value = volume;
|
||||
sync_request(request, ASAPI_ServerMessage::Type::DidSetMainMixVolume);
|
||||
send_sync<ASAPI_Client::SetMainMixVolume>(volume);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Assertions.h>
|
||||
|
||||
struct ASAPI_ServerMessage {
|
||||
enum class Type {
|
||||
Invalid,
|
||||
Greeting,
|
||||
PlayingBuffer,
|
||||
FinishedPlayingBuffer,
|
||||
EnqueueBufferResponse,
|
||||
DidGetMainMixVolume,
|
||||
|
@ -49,3 +50,201 @@ struct ASAPI_ClientMessage {
|
|||
} play_buffer;
|
||||
};
|
||||
};
|
||||
|
||||
// FIXME: Everything below this line should be generated from some kind of IPC protocol description.
|
||||
|
||||
namespace ASAPI_Server {
|
||||
class Greeting;
|
||||
class FinishedPlayingBuffer;
|
||||
class EnqueueBufferResponse;
|
||||
class DidGetMainMixVolume;
|
||||
class DidSetMainMixVolume;
|
||||
}
|
||||
|
||||
namespace ASAPI_Client {
|
||||
|
||||
template<ASAPI_ClientMessage::Type type>
|
||||
class Message {
|
||||
public:
|
||||
static ASAPI_ClientMessage::Type message_type() { return type; }
|
||||
operator const ASAPI_ClientMessage&() const { return m_message; }
|
||||
|
||||
protected:
|
||||
Message()
|
||||
{
|
||||
m_message.type = type;
|
||||
}
|
||||
|
||||
Message(const ASAPI_ClientMessage& message)
|
||||
: m_message(message)
|
||||
{
|
||||
ASSERT(message.type == type);
|
||||
}
|
||||
|
||||
ASAPI_ClientMessage m_message;
|
||||
};
|
||||
|
||||
class Greeting : public Message<ASAPI_ClientMessage::Type::Greeting> {
|
||||
public:
|
||||
typedef ASAPI_Server::Greeting ResponseType;
|
||||
Greeting(const ASAPI_ClientMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
Greeting(int client_pid)
|
||||
{
|
||||
m_message.greeting.client_pid = client_pid;
|
||||
}
|
||||
|
||||
int client_pid() const { return m_message.greeting.client_pid; }
|
||||
};
|
||||
|
||||
class EnqueueBuffer : public Message<ASAPI_ClientMessage::Type::EnqueueBuffer> {
|
||||
public:
|
||||
typedef ASAPI_Server::EnqueueBufferResponse ResponseType;
|
||||
|
||||
EnqueueBuffer(const ASAPI_ClientMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
EnqueueBuffer(int buffer_id)
|
||||
{
|
||||
m_message.play_buffer.buffer_id = buffer_id;
|
||||
}
|
||||
|
||||
int buffer_id() const { return m_message.play_buffer.buffer_id; }
|
||||
};
|
||||
|
||||
class GetMainMixVolume : public Message<ASAPI_ClientMessage::Type::GetMainMixVolume> {
|
||||
public:
|
||||
typedef ASAPI_Server::DidGetMainMixVolume ResponseType;
|
||||
|
||||
GetMainMixVolume(const ASAPI_ClientMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
GetMainMixVolume()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class SetMainMixVolume : public Message<ASAPI_ClientMessage::Type::SetMainMixVolume> {
|
||||
public:
|
||||
typedef ASAPI_Server::DidSetMainMixVolume ResponseType;
|
||||
|
||||
SetMainMixVolume(const ASAPI_ClientMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
SetMainMixVolume(int volume)
|
||||
{
|
||||
m_message.value = volume;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace ASAPI_Server {
|
||||
|
||||
template<ASAPI_ServerMessage::Type type>
|
||||
class Message {
|
||||
public:
|
||||
static ASAPI_ServerMessage::Type message_type() { return type; }
|
||||
operator const ASAPI_ServerMessage&() const { return m_message; }
|
||||
|
||||
protected:
|
||||
Message()
|
||||
{
|
||||
m_message.type = type;
|
||||
}
|
||||
|
||||
Message(const ASAPI_ServerMessage& message)
|
||||
: m_message(message)
|
||||
{
|
||||
ASSERT(message.type == type);
|
||||
}
|
||||
|
||||
ASAPI_ServerMessage m_message;
|
||||
};
|
||||
|
||||
class Greeting : public Message<ASAPI_ServerMessage::Type::Greeting> {
|
||||
public:
|
||||
Greeting(const ASAPI_ServerMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
Greeting(int server_pid, int your_client_id)
|
||||
{
|
||||
m_message.greeting.server_pid = server_pid;
|
||||
m_message.greeting.your_client_id = your_client_id;
|
||||
}
|
||||
|
||||
int server_pid() const { return m_message.greeting.server_pid; }
|
||||
int your_client_id() const { return m_message.greeting.your_client_id; }
|
||||
};
|
||||
|
||||
class FinishedPlayingBuffer : public Message<ASAPI_ServerMessage::Type::FinishedPlayingBuffer> {
|
||||
public:
|
||||
FinishedPlayingBuffer(const ASAPI_ServerMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
FinishedPlayingBuffer(int buffer_id)
|
||||
{
|
||||
m_message.playing_buffer.buffer_id = buffer_id;
|
||||
}
|
||||
|
||||
int buffer_id() const { return m_message.playing_buffer.buffer_id; }
|
||||
};
|
||||
|
||||
class EnqueueBufferResponse : public Message<ASAPI_ServerMessage::Type::EnqueueBufferResponse> {
|
||||
public:
|
||||
EnqueueBufferResponse(const ASAPI_ServerMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
EnqueueBufferResponse(bool success, int buffer_id)
|
||||
{
|
||||
m_message.success = success;
|
||||
m_message.playing_buffer.buffer_id = buffer_id;
|
||||
}
|
||||
|
||||
bool success() const { return m_message.success; }
|
||||
int buffer_id() const { return m_message.playing_buffer.buffer_id; }
|
||||
};
|
||||
|
||||
class DidGetMainMixVolume : public Message<ASAPI_ServerMessage::Type::DidGetMainMixVolume> {
|
||||
public:
|
||||
DidGetMainMixVolume(const ASAPI_ServerMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
DidGetMainMixVolume(int volume)
|
||||
{
|
||||
m_message.value = volume;
|
||||
}
|
||||
|
||||
int volume() const { return m_message.value; }
|
||||
};
|
||||
|
||||
class DidSetMainMixVolume : public Message<ASAPI_ServerMessage::Type::DidSetMainMixVolume> {
|
||||
public:
|
||||
DidSetMainMixVolume(const ASAPI_ServerMessage& message)
|
||||
: Message(message)
|
||||
{
|
||||
}
|
||||
|
||||
DidSetMainMixVolume()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -167,6 +167,18 @@ namespace Client {
|
|||
return response;
|
||||
}
|
||||
|
||||
template<typename RequestType, typename... Args>
|
||||
typename RequestType::ResponseType send_sync(Args&&... args)
|
||||
{
|
||||
bool success = post_message_to_server(RequestType(forward<Args>(args)...));
|
||||
ASSERT(success);
|
||||
|
||||
ServerMessage response;
|
||||
success = wait_for_specific_event(RequestType::ResponseType::message_type(), response);
|
||||
ASSERT(success);
|
||||
return response;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct IncomingMessageBundle {
|
||||
ServerMessage message;
|
||||
|
|
|
@ -25,11 +25,7 @@ ASClientConnection::~ASClientConnection()
|
|||
|
||||
void ASClientConnection::send_greeting()
|
||||
{
|
||||
ASAPI_ServerMessage message;
|
||||
message.type = ASAPI_ServerMessage::Type::Greeting;
|
||||
message.greeting.server_pid = getpid();
|
||||
message.greeting.your_client_id = client_id();
|
||||
post_message(message);
|
||||
post_message(ASAPI_Server::Greeting(getpid(), client_id()));
|
||||
}
|
||||
|
||||
bool ASClientConnection::handle_message(const ASAPI_ClientMessage& message, const ByteBuffer&&)
|
||||
|
@ -53,25 +49,20 @@ bool ASClientConnection::handle_message(const ASAPI_ClientMessage& message, cons
|
|||
m_queue = m_mixer.create_queue(*this);
|
||||
|
||||
if (m_queue->is_full()) {
|
||||
reply.success = false;
|
||||
} else {
|
||||
m_queue->enqueue(ABuffer::create_with_shared_buffer(*shared_buffer));
|
||||
post_message(ASAPI_Server::EnqueueBufferResponse(false, message.play_buffer.buffer_id));
|
||||
break;
|
||||
}
|
||||
post_message(reply);
|
||||
m_queue->enqueue(ABuffer::create_with_shared_buffer(*shared_buffer));
|
||||
post_message(ASAPI_Server::EnqueueBufferResponse(true, message.play_buffer.buffer_id));
|
||||
break;
|
||||
}
|
||||
case ASAPI_ClientMessage::Type::GetMainMixVolume: {
|
||||
ASAPI_ServerMessage reply;
|
||||
reply.type = ASAPI_ServerMessage::Type::DidGetMainMixVolume;
|
||||
reply.value = m_mixer.main_volume();
|
||||
post_message(reply);
|
||||
post_message(ASAPI_Server::DidGetMainMixVolume(m_mixer.main_volume()));
|
||||
break;
|
||||
}
|
||||
case ASAPI_ClientMessage::Type::SetMainMixVolume: {
|
||||
ASAPI_ServerMessage reply;
|
||||
reply.type = ASAPI_ServerMessage::Type::DidSetMainMixVolume;
|
||||
m_mixer.set_main_volume(message.value);
|
||||
post_message(reply);
|
||||
post_message(ASAPI_Server::DidSetMainMixVolume());
|
||||
break;
|
||||
}
|
||||
case ASAPI_ClientMessage::Type::Invalid:
|
||||
|
@ -85,8 +76,5 @@ bool ASClientConnection::handle_message(const ASAPI_ClientMessage& message, cons
|
|||
|
||||
void ASClientConnection::did_finish_playing_buffer(Badge<ASMixer>, int buffer_id)
|
||||
{
|
||||
ASAPI_ServerMessage reply;
|
||||
reply.type = ASAPI_ServerMessage::Type::FinishedPlayingBuffer;
|
||||
reply.playing_buffer.buffer_id = buffer_id;
|
||||
post_message(reply);
|
||||
post_message(ASAPI_Server::FinishedPlayingBuffer(buffer_id));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue