231 lines
5.2 KiB
C++
231 lines
5.2 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace warppipe {
|
|
|
|
enum class StatusCode : uint8_t {
|
|
kOk = 0,
|
|
kInvalidArgument,
|
|
kNotFound,
|
|
kUnavailable,
|
|
kPermissionDenied,
|
|
kTimeout,
|
|
kInternal,
|
|
kNotImplemented,
|
|
};
|
|
|
|
struct Status {
|
|
StatusCode code = StatusCode::kOk;
|
|
std::string message;
|
|
|
|
static Status Ok();
|
|
static Status Error(StatusCode code, std::string message);
|
|
bool ok() const;
|
|
};
|
|
|
|
template <typename T>
|
|
struct Result {
|
|
Status status;
|
|
T value{};
|
|
|
|
bool ok() const { return status.ok(); }
|
|
};
|
|
|
|
enum class ThreadingMode : uint8_t {
|
|
kCallerThread = 0,
|
|
kThreadLoop,
|
|
};
|
|
|
|
struct ConnectionOptions {
|
|
ThreadingMode threading = ThreadingMode::kThreadLoop;
|
|
bool autoconnect = true;
|
|
bool policy_only = false;
|
|
std::string application_name = "warppipe";
|
|
std::optional<std::string> remote_name;
|
|
std::optional<std::string> config_path;
|
|
};
|
|
|
|
struct AudioFormat {
|
|
uint32_t rate = 48000;
|
|
uint32_t channels = 2;
|
|
};
|
|
|
|
enum class VirtualBehavior : uint8_t {
|
|
kNull = 0,
|
|
kLoopback,
|
|
};
|
|
|
|
struct VirtualNodeOptions {
|
|
AudioFormat format{};
|
|
VirtualBehavior behavior = VirtualBehavior::kNull;
|
|
std::optional<std::string> target_node;
|
|
std::optional<std::string> media_class_override;
|
|
std::string display_name;
|
|
std::string group;
|
|
};
|
|
|
|
struct NodeId {
|
|
uint32_t value = 0;
|
|
};
|
|
|
|
struct PortId {
|
|
uint32_t value = 0;
|
|
};
|
|
|
|
struct LinkId {
|
|
uint32_t value = 0;
|
|
};
|
|
|
|
struct RuleId {
|
|
uint32_t value = 0;
|
|
};
|
|
|
|
struct NodeInfo {
|
|
NodeId id;
|
|
std::string name;
|
|
std::string description;
|
|
std::string media_class;
|
|
std::string application_name;
|
|
std::string process_binary;
|
|
std::string media_role;
|
|
bool is_virtual = false;
|
|
};
|
|
|
|
struct PortInfo {
|
|
PortId id;
|
|
NodeId node;
|
|
std::string name;
|
|
bool is_input = false;
|
|
};
|
|
|
|
struct VirtualSink {
|
|
NodeId node;
|
|
std::string name;
|
|
};
|
|
|
|
struct VirtualSource {
|
|
NodeId node;
|
|
std::string name;
|
|
};
|
|
|
|
struct Link {
|
|
LinkId id;
|
|
PortId output_port;
|
|
PortId input_port;
|
|
};
|
|
|
|
struct LinkOptions {
|
|
bool passive = false;
|
|
bool linger = false;
|
|
};
|
|
|
|
struct RuleMatch {
|
|
std::string application_name;
|
|
std::string process_binary;
|
|
std::string media_role;
|
|
};
|
|
|
|
struct RouteRule {
|
|
RuleId id;
|
|
RuleMatch match;
|
|
std::string target_node;
|
|
};
|
|
|
|
struct VolumeState {
|
|
float volume = 1.0f;
|
|
bool mute = false;
|
|
};
|
|
|
|
struct MeterState {
|
|
float peak_left = 0.0f;
|
|
float peak_right = 0.0f;
|
|
};
|
|
|
|
struct MetadataInfo {
|
|
std::string default_sink_name;
|
|
std::string default_source_name;
|
|
std::string configured_sink_name;
|
|
std::string configured_source_name;
|
|
};
|
|
|
|
class Client {
|
|
public:
|
|
Client(const Client&) = delete;
|
|
Client& operator=(const Client&) = delete;
|
|
Client(Client&&) noexcept;
|
|
Client& operator=(Client&&) noexcept;
|
|
~Client();
|
|
|
|
static Result<std::unique_ptr<Client>> Create(const ConnectionOptions& options);
|
|
|
|
Status Shutdown();
|
|
|
|
Result<std::vector<NodeInfo>> ListNodes();
|
|
Result<std::vector<PortInfo>> ListPorts(NodeId node);
|
|
Result<std::vector<Link>> ListLinks();
|
|
|
|
Result<VirtualSink> CreateVirtualSink(std::string_view name,
|
|
const VirtualNodeOptions& options = VirtualNodeOptions{});
|
|
Result<VirtualSource> CreateVirtualSource(std::string_view name,
|
|
const VirtualNodeOptions& options = VirtualNodeOptions{});
|
|
Status RemoveNode(NodeId node);
|
|
|
|
Status SetNodeVolume(NodeId node, float volume, bool mute);
|
|
Result<VolumeState> GetNodeVolume(NodeId node) const;
|
|
|
|
Status EnsureNodeMeter(NodeId node);
|
|
Status DisableNodeMeter(NodeId node);
|
|
Result<MeterState> NodeMeterPeak(NodeId node) const;
|
|
Result<MeterState> MeterPeak() const;
|
|
|
|
Result<Link> CreateLink(PortId output, PortId input, const LinkOptions& options);
|
|
Result<Link> CreateLinkByName(std::string_view output_node,
|
|
std::string_view output_port,
|
|
std::string_view input_node,
|
|
std::string_view input_port,
|
|
const LinkOptions& options);
|
|
Status RemoveLink(LinkId link);
|
|
|
|
Result<RuleId> AddRouteRule(const RouteRule& rule);
|
|
Status RemoveRouteRule(RuleId id);
|
|
Result<std::vector<RouteRule>> ListRouteRules();
|
|
|
|
Result<MetadataInfo> GetDefaults();
|
|
Status SetDefaultSink(std::string_view node_name);
|
|
Status SetDefaultSource(std::string_view node_name);
|
|
|
|
Status SaveConfig(std::string_view path);
|
|
Status LoadConfig(std::string_view path);
|
|
|
|
using ChangeCallback = std::function<void()>;
|
|
void SetChangeCallback(ChangeCallback callback);
|
|
|
|
#ifdef WARPPIPE_TESTING
|
|
Status Test_InsertNode(const NodeInfo& node);
|
|
Status Test_InsertPort(const PortInfo& port);
|
|
Status Test_InsertLink(const Link& link);
|
|
Status Test_RemoveGlobal(uint32_t id);
|
|
Status Test_ForceDisconnect();
|
|
Status Test_TriggerPolicyCheck();
|
|
size_t Test_GetPendingAutoLinkCount() const;
|
|
Status Test_SetNodeVolume(NodeId node, float volume, bool mute);
|
|
Result<VolumeState> Test_GetNodeVolume(NodeId node) const;
|
|
Status Test_SetNodeMeterPeak(NodeId node, float left, float right);
|
|
Status Test_SetMasterMeterPeak(float left, float right);
|
|
#endif
|
|
|
|
private:
|
|
struct Impl;
|
|
explicit Client(std::unique_ptr<Impl> impl);
|
|
|
|
std::unique_ptr<Impl> impl_;
|
|
};
|
|
|
|
} // namespace warppipe
|